diff --git a/.github/workflows/image-compression.yml b/.github/workflows/image-compression.yml new file mode 100644 index 0000000000..9cbaa00d90 --- /dev/null +++ b/.github/workflows/image-compression.yml @@ -0,0 +1,21 @@ +name: Compress Images +on: + pull_request: + paths: + - '**.jpg' + - '**.jpeg' + - '**.png' + - '**.webp' +jobs: + build: + if: github.event.pull_request.head.repo.full_name == github.repository + name: calibreapp/image-actions + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v2 + + - name: Compress Images + uses: calibreapp/image-actions@main + with: + githubToken: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3c5c4f89da..2f820efc4d 100644 --- a/.gitignore +++ b/.gitignore @@ -310,4 +310,7 @@ abp-build-config.json /templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/Pages/Test/ # Identity Server temp signature file -tempkey.jwk \ No newline at end of file +tempkey.jwk + +# ABP Analyzing files +*.abppkg.analyze.json \ No newline at end of file diff --git a/README.md b/README.md index bac7fd197f..21bc8ab85f 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,9 @@ ABP Framework is a complete **infrastructure** based on the **ASP.NET Core** to ## Getting Started -- [Getting Started Guide](https://docs.abp.io/en/abp/latest/Getting-Started) is the easiest way to start a new web application with the ABP Framework. -- [Web Application Development Tutorial](https://docs.abp.io/en/abp/latest/Tutorials/Part-1) is a complete tutorial to develop a full stack web application. +- [Quick Start](https://docs.abp.io/en/abp/latest/Tutorials/Todo/Index) is a single-part, quick-start tutorial to build a simple application with the ABP Framework. Start with this tutorial if you want to quickly understand how ABP works. +- [Getting Started guide](https://docs.abp.io/en/abp/latest/Getting-Started) can be used to create and run ABP based solutions with different options and details. +- [Web Application Development Tutorial](https://docs.abp.io/en/abp/latest/Tutorials/Part-1) is a complete tutorial to develop a full stack web application with all aspects of a real-life solution. ### Quick Start diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/fi.json new file mode 100644 index 0000000000..0ed3c1f6db --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/fi.json @@ -0,0 +1,14 @@ +{ + "culture": "fi", + "texts": { + "Account": "ABP-tili - Kirjaudu ja rekisteröidy | ABP.IO", + "Welcome": "Tervetuloa", + "UseOneOfTheFollowingLinksToContinue": "Käytä yhtä seuraavista linkeistä jatkaaksesi", + "FrameworkHomePage": "Kehyksen kotisivu", + "FrameworkDocumentation": "Puitteet", + "OfficialBlog": "Virallinen blogi", + "CommercialHomePage": "Kaupallinen kotisivu", + "CommercialSupportWebSite": "Kaupallisen tuen verkkosivusto", + "CommunityWebSite": "ABP-yhteisön verkkosivusto" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/fr.json new file mode 100644 index 0000000000..5129f098e1 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/fr.json @@ -0,0 +1,14 @@ +{ + "culture": "fr", + "texts": { + "Account": "Compte ABP - Connexion et enregistrement | ABP.IO", + "Welcome": "Bienvenue", + "UseOneOfTheFollowingLinksToContinue": "Utilisez l'un des liens suivants pour continuer", + "FrameworkHomePage": "Page d'accueil du framework", + "FrameworkDocumentation": "Documentation du framework", + "OfficialBlog": "Blog officiel", + "CommercialHomePage": "Page d'accueil commerciale", + "CommercialSupportWebSite": "Site Web de support commercial", + "CommunityWebSite": "Site Web de la communauté ABP" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/hi.json new file mode 100644 index 0000000000..2029996445 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/hi.json @@ -0,0 +1,14 @@ +{ + "culture": "hi", + "texts": { + "Account": "ABP खाता - लॉगिन और रजिस्टर | ABP.IO", + "Welcome": "स्वागत हे", + "UseOneOfTheFollowingLinksToContinue": "जारी रखने के लिए निम्न लिंक में से एक का उपयोग करें", + "FrameworkHomePage": "फ्रेमवर्क होम पेज", + "FrameworkDocumentation": "फ्रेमवर्क प्रलेखन", + "OfficialBlog": "आधिकारिक ब्लॉग", + "CommercialHomePage": "वाणिज्यिक मुख पृष्ठ", + "CommercialSupportWebSite": "वाणिज्यिक समर्थन वेब साइट", + "CommunityWebSite": "एबीपी सामुदायिक वेब साइट" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/it.json new file mode 100644 index 0000000000..6dada8fba7 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/it.json @@ -0,0 +1,14 @@ +{ + "culture": "it", + "texts": { + "Account": "Account ABP - Accesso e registrazione | ABP.IO", + "Welcome": "benvenuto", + "UseOneOfTheFollowingLinksToContinue": "Usa uno dei seguenti link per continuare", + "FrameworkHomePage": "Home page del framework", + "FrameworkDocumentation": "Documentazione del framework", + "OfficialBlog": "Blog ufficiale", + "CommercialHomePage": "Home page commerciale", + "CommercialSupportWebSite": "Sito web di supporto commerciale", + "CommunityWebSite": "Sito web della comunità ABP" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 09d93b946c..0cfd2a477a 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -272,6 +272,11 @@ "PaymentProduct": "Payment Product", "ProductName": "Product Name", "Code": "Code", - "GenerateInvoice": "Generate Invoice" + "GenerateInvoice": "Generate Invoice", + "ExportOrganizationsToExcel": "Export to Excel", + "ThisExtensionIsNotAllowed": "This extension is not allowed.", + "TheFileIsTooLarge": "The file is too large!", + "ArticleDeletionConfirmationMessage": "Are you sure you want to hard delete this article?", + "ChooseCoverImage": "Choose a cover image..." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fi.json new file mode 100644 index 0000000000..488e07a1d0 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fi.json @@ -0,0 +1,282 @@ +{ + "culture": "fi", + "texts": { + "Permission:Organizations": "Organisaatiot", + "Permission:Manage": "Hallitse organisaatioita", + "Permission:DiscountRequests": "Alennushakemukset", + "Permission:DiscountManage": "Hallitse alennuspyyntöjä", + "Permission:Disable": "Poista käytöstä", + "Permission:Enable": "ota käyttöön", + "Permission:EnableSendEmail": "Ota Lähetä sähköposti käyttöön", + "Permission:SendEmail": "Lähettää sähköpostia", + "Permission:NpmPackages": "NPM-paketit", + "Permission:NugetPackages": "Nuget-paketit", + "Permission:Maintenance": "Huolto", + "Permission:Maintain": "Ylläpitää", + "Permission:ClearCaches": "Tyhjennä välimuistit", + "Permission:Modules": "Moduulit", + "Permission:Packages": "Paketit", + "Permission:Edit": "Muokata", + "Permission:Delete": "Poistaa", + "Permission:Create": "Luoda", + "Permission:Accounting": "Kirjanpito", + "Permission:Accounting:Quotation": "Tarjous", + "Permission:Accounting:Invoice": "Lasku", + "Menu:Organizations": "Organisaatiot", + "Menu:Accounting": "Kirjanpito", + "Menu:Packages": "Paketit", + "Menu:DiscountRequests": "Alennushakemukset", + "NpmPackageDeletionWarningMessage": "Tämä NPM-paketti poistetaan. Vahvistatko sen?", + "NugetPackageDeletionWarningMessage": "Tämä Nuget-paketti poistetaan. Vahvistatko sen?", + "ModuleDeletionWarningMessage": "Tämä moduuli poistetaan. Vahvistatko sen?", + "Name": "Nimi", + "DisplayName": "Näyttönimi", + "ShortDescription": "Lyhyt kuvaus", + "NameFilter": "Nimi", + "CreationTime": "Luomisaika", + "IsPro": "On ammattilainen", + "IsFreeToActiveLicenseOwners": "Vapaa lisenssin omistajille", + "ShowOnModuleList": "Näytä moduuliluettelossa", + "EfCoreConfigureMethodName": "Määritä menetelmän nimi", + "IsProFilter": "On ammattilainen", + "ApplicationType": "Sovelluksen tyyppi", + "Target": "Kohde", + "TargetFilter": "Kohde", + "ModuleClass": "Moduuliluokka", + "NugetPackageTarget.DomainShared": "Verkkotunnus jaettu", + "NugetPackageTarget.Domain": "Verkkotunnus", + "NugetPackageTarget.Application": "Sovellus", + "NugetPackageTarget.ApplicationContracts": "Sovellussopimukset", + "NugetPackageTarget.HttpApi": "Http Api", + "NugetPackageTarget.HttpApiClient": "Http Api Client", + "NugetPackageTarget.Web": "Web", + "NugetPackageTarget.EntityFrameworkCore": "PoistaAllEntityFramework Core", + "NugetPackageTarget.MongoDB": "MongoDB", + "Edit": "Muokata", + "Delete": "Poistaa", + "Refresh": "virkistää", + "NpmPackages": "NPM-paketit", + "NugetPackages": "Nuget-paketit", + "NpmPackageCount": "NPM-pakettimäärä", + "NugetPackageCount": "Nugetin pakettimäärä", + "Module": "Moduulit", + "ModuleInfo": "Moduulin tiedot", + "CreateANpmPackage": "Luo NPM-paketti", + "CreateAModule": "Luo moduuli", + "CreateANugetPackage": "Luo Nuget-paketti", + "AddNew": "Lisää uusi", + "PackageAlreadyExist{0}": "Paketti \"{0}\" on jo lisätty.", + "ModuleAlreadyExist{0}": "\"{0}\" -moduuli on jo lisätty.", + "ClearCache": "Tyhjennä välimuisti", + "SuccessfullyCleared": "Tyhjennetty onnistuneesti", + "Menu:NpmPackages": "NPM-paketit", + "Menu:Modules": "Moduulit", + "Menu:Maintenance": "Huolto", + "Menu:NugetPackages": "Nuget-paketit", + "CreateAnOrganization": "Luo organisaatio", + "Organizations": "Organisaatiot", + "LongName": "Pitkä nimi", + "LicenseType": "Lisenssi-tyyppi", + "MissingLicenseTypeField": "Lisenssityyppikenttä vaaditaan!", + "LicenseStartTime": "Lisenssin aloitusaika", + "LicenseEndTime": "Lisenssin päättymisaika", + "AllowedDeveloperCount": "Sallittu kehittäjien määrä", + "UserNameOrEmailAddress": "Käyttäjänimi tai Sähköpostiosoite", + "AddOwner": "Lisää omistaja", + "UserName": "Käyttäjätunnus", + "Email": "Sähköposti", + "Developers": "Kehittäjät", + "AddDeveloper": "Lisää kehittäjä", + "Create": "Luoda", + "UserNotFound": "Käyttäjää ei löydy", + "{0}WillBeRemovedFromDevelopers": "{0} Poistetaanko kehittäjiltä, vahvistatko?", + "{0}WillBeRemovedFromOwners": "{0} Poistetaanko omistajilta, vahvistatko?", + "{0}WillBeRemovedFromMembers": "{0} Poistetaanko jäsenistä, vahvistatko?", + "Computers": "Tietokoneet", + "UniqueComputerId": "Ainutlaatuinen tietokoneen tunnus", + "LastSeenDate": "Viimeksi nähty päivämäärä", + "{0}Computer{1}WillBeRemovedFromRecords": "Käyttäjän {0} ({1}) tietokone poistetaan tietueista", + "OrganizationDeletionWarningMessage": "Organisaatio poistetaan", + "DeletingLastOwnerWarningMessage": "Organisaatiolla on oltava vähintään yksi omistaja! Siksi et voi poistaa tätä omistajaa", + "This{0}AlreadyExistInThisOrganization": "Tämä {0} on jo olemassa tässä organisaatiossa", + "AreYouSureYouWantToDeleteAllComputers": "Haluatko varmasti poistaa kaikki tietokoneet?", + "DeleteAll": "Poista kaikki", + "DoYouWantToCreateNewUser": "Haluatko luoda uuden käyttäjän?", + "MasterModules": "Master-moduulit", + "OrganizationName": "Organisaation nimi", + "CreationDate": "Luomispäivä", + "LicenseStartDate": "Lisenssin aloituspäivä", + "LicenseEndDate": "Lisenssin päättymispäivä", + "OrganizationNamePlaceholder": "Organisaation nimi...", + "TotalQuestionCountPlaceholder": "Kysymysten kokonaismäärä ...", + "RemainingQuestionCountPlaceholder": "Jäljellä oleva kysymysten määrä ...", + "LicenseTypePlaceholder": "Lisenssi-tyyppi...", + "CreationDatePlaceholder": "Luomispäivä...", + "LicenseStartDatePlaceholder": "Lisenssin aloituspäivä ...", + "LicenseEndDatePlaceholder": "Lisenssin päättymispäivä ...", + "UsernameOrEmail": "Käyttäjätunnus tai sähköpostiosoite", + "UsernameOrEmailPlaceholder": "Käyttäjätunnus tai sähköpostiosoite...", + "Member": "Jäsen", + "PurchaseOrderNo": "Ostotilaus nro", + "QuotationDate": "Tarjouspäivä", + "CompanyName": "Yrityksen nimi", + "CompanyAddress": "Yritys osoite", + "Price": "Hinta", + "DiscountText": "Alennusteksti", + "DiscountQuantity": "Alennusmäärä", + "DiscountPrice": "Alennushinta", + "Quotation": "Tarjous", + "ExtraText": "Lisäteksti", + "ExtraAmount": "Lisämäärä", + "DownloadQuotation": "Lataa tarjous", + "Invoice": "Lasku", + "TaxNumber": "Veronumero", + "InvoiceNumber": "Laskun numero", + "InvoiceDate": "Laskutus päivämäärä", + "InvoiceNote": "Laskuhuomautus", + "Quantity": "Määrä", + "AddProduct": "Lisää tuote", + "AddProductWarning": "Sinun on lisättävä tuote!", + "TotalPrice": "Kokonaishinta", + "Generate": "Tuottaa", + "MissingQuantityField": "Määrä-kenttä vaaditaan!", + "MissingPriceField": "Hinta-kenttä on pakollinen!", + "CodeUsageStatus": "Tila", + "Country": "Maa", + "DeveloperCount": "Kehittäjien määrä", + "RequestCode": "Varauskoodi", + "WebSite": "Verkkosivusto", + "GithubUsername": "Github-käyttäjätunnus", + "PhoneNumber": "Puhelinnumero", + "ProjectDescription": "Hankkeen kuvaus", + "Referrer": "Viittaaja", + "DiscountRequests": "Alennuspyyntö", + "Copylink": "Kopioi linkki", + "Disable": "Poista käytöstä", + "Enable": "ota käyttöön", + "EnableSendEmail": "Ota Lähetä sähköposti käyttöön", + "SendEmail": "Lähettää sähköpostia", + "SuccessfullyDisabled": "Poistettu onnistuneesti käytöstä", + "SuccessfullyEnabled": "Ota käyttöön", + "EmailSent": "Sähköposti lähetetty", + "SuccessfullySent": "Lähetetty onnistuneesti", + "SuccessfullyDeleted": "Poistaminen onnistui", + "DiscountRequestDeletionWarningMessage": "Alennuspyyntö poistetaan", + "BusinessType": "Yritystyyppi", + "TotalQuestionCount": "Kysymysten kokonaismäärä", + "RemainingQuestionCount": "Jäljellä oleva kysymyslaskenta", + "TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCountin on oltava suurempi kuin RemainingQuestionCount!", + "QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount ja RemainingQuestionCount on oltava nolla tai suurempi kuin nolla!", + "UnlimitedQuestionCount": "Rajoittamaton kysymysten määrä", + "Notes": "Huomautuksia", + "Menu:Community": "Yhteisö", + "Menu:Articles": "Artikkelit", + "Wait": "Odota", + "Approve": "Hyväksyä", + "Reject": "Hylätä", + "Details": "Yksityiskohdat", + "Url": "URL-osoite", + "Title": "Otsikko", + "ContentSource": "Sisältölähde", + "Status": "Tila", + "ReadArticle": "Lue artikkeli", + "ArticleHasBeenWaiting": "Artikkeli on odottanut", + "ArticleHasBeenApproved": "Artikkeli on hyväksytty", + "ArticleHasBeenRejected": "Artikkeli on hylätty", + "Permission:Community": "Yhteisö", + "Permission:CommunityArticle": "Artikla", + "Link": "Linkki", + "Enum:ContentSource:0": "Github", + "Enum:ContentSource:1": "Ulkoinen", + "Enum:Status:0": "Odottaa", + "Enum:Status:1": "Hylätty", + "Enum:Status:2": "Hyväksytty", + "Summary": "Yhteenveto", + "AuthorName": "Kirjoittajan nimi", + "CoverImage": "Kansikuva", + "RemoveCacheConfirmationMessage": "Oletko varma, että poistat artikkelin {0} välimuistin?", + "SuccessfullyRemoved": "Tyhjennetty onnistuneesti", + "RemoveCache": "Poista välimuisti", + "Language": "Kieli", + "Optional": "Valinnainen", + "CreateArticleLanguageInfo": "Kieli, jolla viesti kirjoitetaan", + "Enum:ContentSource:2": "Videoposti", + "VideoPreview": "Videon esikatselu", + "VideoPreviewErrorMessage": "Annettua videon URL-osoitetta ei voitu noutaa Youtubesta. Tämä voi johtua siitä, että video on yksityinen tai annettu URL-osoite ei ole käytettävissä.", + "DeleteCoverImage": "Poista kansikuva", + "DeleteCoverImageConfirmationMessage": "Haluatko varmasti poistaa kansion \"{0}\" kansikuvan?", + "DeleteCoverImageSuccessMessage": "Kansikuvan poistaminen onnistui", + "PaymentsOf": "Maksut", + "ShowPaymentsOfOrganization": "Maksut", + "Date": "Päivämäärä", + "Products": "Tuotteet", + "TotalAmount": "Kokonaismäärä", + "Currency": "Valuutta", + "Gateway": "Yhdyskäytävä", + "State": "Osavaltio", + "FailReason": "Epäonnistunut syy", + "ReIndexAllPosts": "Reindex Kaikki viestit", + "ReIndexAllPostsConfirmationMessage": "Haluatko varmasti indeksoida kaikki viestit uudelleen?", + "SuccessfullyReIndexAllPosts": "Kaikki viestit on indeksoitu uudelleen.", + "Permission:FullSearch": "Koko tekstihaku", + "Menu:CliAnalytics": "Cli Analytics", + "TemplateName": "Mallin nimi", + "TemplateVersion": "Malliversio", + "DatabaseProvider": "Tietokannan tarjoaja", + "IsTiered": "Onko porrastettu", + "ProjectName": "Projektin nimi", + "Username": "Käyttäjänimi", + "Tool": "Työkalu", + "Command": "Komento", + "UiFramework": "Ui-kehys", + "Options": "Vaihtoehdot", + "CliAnalytics": "Cli Analytics", + "Permission:CliAnalyticses": "Cli Analyticses", + "Permission:CliAnalytics": "Cli Analytics", + "Search": "Hae", + "ClearFilter": "Tyhjennä suodatin", + "LicensePrivateKey": "Lisenssin yksityinen avain", + "LicensePublicKey": "Lisenssin julkinen avain", + "ApiKey": "NuGet API -avain", + "ShowInvoiceRequestsOfOrganization": "Laskupyynnöt", + "ShowQuestionsOfOrganization": "Kysymyksiä", + "Question": "Kysymys", + "Open": "Avata", + "Questions": "Kysymyksiä", + "InvoiceRequests": "Laskupyynnöt", + "Address": "Osoite", + "TaxNo": "Veronumero", + "Permission:InvoiceRequest": "Laskutuspyyntö", + "Permission:Question": "Kysymys", + "AddNoteSuccessMessage": "Muistiinpanon lisääminen onnistui", + "NameSurname": "Nimi sukunimi", + "Note": "Merkintä", + "Add": "Lisätä", + "ProjectDownloads": "Projektin lataukset", + "ShowProjectDownloadsOfOrganization": "Projektin lataukset", + "ShowAuditLogsOfOrganization": "Tarkastuslokit", + "Enum:EntityChangeType:0": "Luotu", + "Enum:EntityChangeType:1": "Päivitetty", + "Enum:EntityChangeType:2": "Poistettu", + "TenantId": "Vuokralaisen tunnus", + "ChangeTime": "Vaihda aikaa", + "EntityTypeFullName": "Yhteisön tyypin koko nimi", + "AuditLogsFor{0}Organization": "\"{0}\" -organisaation tarkastuslokit", + "Permission:EntityChange": "Entity Change", + "Permission:ProjectDownload": "Projektin lataus", + "Permission:PaymentRequest": "Maksupyyntö", + "CreatorEmailAddress": "Sisällöntuottajan sähköpostiosoite", + "EmailSendDate": "Sähköpostin lähetyspäivä", + "PaymentRequestsFor{0}Organization": "Maksupyynnöt organisaatiolle {0}", + "PaymentDetails": "Maksutiedot", + "PaymentProduct": "Maksutuote", + "ProductName": "tuotteen nimi", + "Code": "Koodi", + "GenerateInvoice": "Luo lasku", + "ExportOrganizationsToExcel": "Vie Exceliin", + "ThisExtensionIsNotAllowed": "Tätä laajennusta ei sallita.", + "TheFileIsTooLarge": "Tiedosto on liian suuri!", + "ArticleDeletionConfirmationMessage": "Haluatko varmasti poistaa tämän artikkelin vaikeasti?", + "ChooseCoverImage": "Valitse kansikuva ..." + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fr.json new file mode 100644 index 0000000000..2a2d8ba568 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fr.json @@ -0,0 +1,282 @@ +{ + "culture": "fr", + "texts": { + "Permission:Organizations": "Organisations", + "Permission:Manage": "Gérer les organisations", + "Permission:DiscountRequests": "Demandes de remise", + "Permission:DiscountManage": "Gérer les demandes de remise", + "Permission:Disable": "Désactiver", + "Permission:Enable": "Activer", + "Permission:EnableSendEmail": "Activer l'envoi d'e-mail", + "Permission:SendEmail": "Envoyer un e-mail", + "Permission:NpmPackages": "Packages NPM", + "Permission:NugetPackages": "Packages Nuget", + "Permission:Maintenance": "Maintenance", + "Permission:Maintain": "Maintenir", + "Permission:ClearCaches": "Effacer les caches", + "Permission:Modules": "Modules", + "Permission:Packages": "Paquets", + "Permission:Edit": "Éditer", + "Permission:Delete": "Effacer", + "Permission:Create": "Créer", + "Permission:Accounting": "Comptabilité", + "Permission:Accounting:Quotation": "Devis", + "Permission:Accounting:Invoice": "Facturer", + "Menu:Organizations": "Organisations", + "Menu:Accounting": "Comptabilité", + "Menu:Packages": "Paquets", + "Menu:DiscountRequests": "Demandes de remise", + "NpmPackageDeletionWarningMessage": "Ce package NPM sera supprimé. Le confirmez-vous?", + "NugetPackageDeletionWarningMessage": "Ce package Nuget sera supprimé. Le confirmez-vous?", + "ModuleDeletionWarningMessage": "Ce module sera supprimé. Le confirmez-vous?", + "Name": "Nom", + "DisplayName": "Afficher un nom", + "ShortDescription": "Brève description", + "NameFilter": "Nom", + "CreationTime": "Temps de creation", + "IsPro": "Est pro", + "IsFreeToActiveLicenseOwners": "Gratuit pour les titulaires de licence", + "ShowOnModuleList": "Afficher sur la liste des modules", + "EfCoreConfigureMethodName": "Configurer le nom de la méthode", + "IsProFilter": "Est pro", + "ApplicationType": "Type d'application", + "Target": "Cible", + "TargetFilter": "Cible", + "ModuleClass": "Classe de module", + "NugetPackageTarget.DomainShared": "Domaine partagé", + "NugetPackageTarget.Domain": "Domaine", + "NugetPackageTarget.Application": "Application", + "NugetPackageTarget.ApplicationContracts": "Contrats d'application", + "NugetPackageTarget.HttpApi": "Http Api", + "NugetPackageTarget.HttpApiClient": "Client Api Http", + "NugetPackageTarget.Web": "Web", + "NugetPackageTarget.EntityFrameworkCore": "DeleteAllEntityFramework Core", + "NugetPackageTarget.MongoDB": "MongoDB", + "Edit": "Éditer", + "Delete": "Effacer", + "Refresh": "Rafraîchir", + "NpmPackages": "Packages NPM", + "NugetPackages": "Packages Nuget", + "NpmPackageCount": "Nombre de packages NPM", + "NugetPackageCount": "Nombre de paquets Nuget", + "Module": "Modules", + "ModuleInfo": "Informations sur le module", + "CreateANpmPackage": "Créer un package NPM", + "CreateAModule": "Créer un module", + "CreateANugetPackage": "Créer un package Nuget", + "AddNew": "Ajouter un nouveau", + "PackageAlreadyExist{0}": "Le package \"{0}\" est déjà ajouté.", + "ModuleAlreadyExist{0}": "Le module \"{0}\" est déjà ajouté.", + "ClearCache": "Vider le cache", + "SuccessfullyCleared": "Effacé avec succès", + "Menu:NpmPackages": "Packages NPM", + "Menu:Modules": "Modules", + "Menu:Maintenance": "Maintenance", + "Menu:NugetPackages": "Packages Nuget", + "CreateAnOrganization": "Créer une organisation", + "Organizations": "Organisations", + "LongName": "Nom long", + "LicenseType": "Type de licence", + "MissingLicenseTypeField": "Le champ du type de licence est obligatoire!", + "LicenseStartTime": "Heure de début de la licence", + "LicenseEndTime": "Heure de fin de la licence", + "AllowedDeveloperCount": "Nombre de développeurs autorisé", + "UserNameOrEmailAddress": "Nom d'utilisateur ou adresse e-mail", + "AddOwner": "Ajouter un propriétaire", + "UserName": "Nom d'utilisateur", + "Email": "E-mail", + "Developers": "Les développeurs", + "AddDeveloper": "Ajouter un développeur", + "Create": "Créer", + "UserNotFound": "Utilisateur non trouvé", + "{0}WillBeRemovedFromDevelopers": "{0} Sera supprimé des développeurs, confirmez-vous?", + "{0}WillBeRemovedFromOwners": "{0} Sera supprimé des propriétaires, confirmez-vous?", + "{0}WillBeRemovedFromMembers": "{0} Sera supprimé des membres, confirmez-vous?", + "Computers": "Ordinateurs", + "UniqueComputerId": "ID d'ordinateur unique", + "LastSeenDate": "Date de la dernière consultation", + "{0}Computer{1}WillBeRemovedFromRecords": "L'ordinateur de {0} ({1}) sera supprimé des enregistrements", + "OrganizationDeletionWarningMessage": "L'organisation sera supprimée", + "DeletingLastOwnerWarningMessage": "Une organisation doit avoir au moins un propriétaire! Par conséquent, vous ne pouvez pas supprimer ce propriétaire", + "This{0}AlreadyExistInThisOrganization": "Ce {0} existe déjà dans cette organisation", + "AreYouSureYouWantToDeleteAllComputers": "Voulez-vous vraiment supprimer tous les ordinateurs?", + "DeleteAll": "Tout supprimer", + "DoYouWantToCreateNewUser": "Voulez-vous créer un nouvel utilisateur?", + "MasterModules": "Modules maîtres", + "OrganizationName": "Nom de l'organisation", + "CreationDate": "Date de création", + "LicenseStartDate": "Date de début de la licence", + "LicenseEndDate": "Date de fin de licence", + "OrganizationNamePlaceholder": "Nom de l'organisation...", + "TotalQuestionCountPlaceholder": "Nombre total de questions ...", + "RemainingQuestionCountPlaceholder": "Nombre de questions restantes ...", + "LicenseTypePlaceholder": "Type de licence...", + "CreationDatePlaceholder": "Date de création...", + "LicenseStartDatePlaceholder": "Date de début de la licence ...", + "LicenseEndDatePlaceholder": "Date de fin de licence ...", + "UsernameOrEmail": "Nom d'utilisateur ou email", + "UsernameOrEmailPlaceholder": "Nom d'utilisateur ou email...", + "Member": "Membre", + "PurchaseOrderNo": "Bon de commande non", + "QuotationDate": "Date du devis", + "CompanyName": "Nom de la société", + "CompanyAddress": "Adresse de la société", + "Price": "Prix", + "DiscountText": "Texte de remise", + "DiscountQuantity": "Quantité de remise", + "DiscountPrice": "Prix bas", + "Quotation": "Devis", + "ExtraText": "Texte supplémentaire", + "ExtraAmount": "Montant supplémentaire", + "DownloadQuotation": "Télécharger le devis", + "Invoice": "Facturer", + "TaxNumber": "Numéro d'identification fiscale", + "InvoiceNumber": "Numéro de facture", + "InvoiceDate": "Date de la facture", + "InvoiceNote": "Note sur la facture", + "Quantity": "Quantité", + "AddProduct": "Ajouter un produit", + "AddProductWarning": "Vous devez ajouter un produit!", + "TotalPrice": "Prix total", + "Generate": "Générer", + "MissingQuantityField": "Le champ de quantité est obligatoire!", + "MissingPriceField": "Le champ Prix est obligatoire!", + "CodeUsageStatus": "Statut", + "Country": "Pays", + "DeveloperCount": "Nombre de développeurs", + "RequestCode": "Code requis", + "WebSite": "Site Internet", + "GithubUsername": "Nom d'utilisateur Github", + "PhoneNumber": "Numéro de téléphone", + "ProjectDescription": "Description du projet", + "Referrer": "Référent", + "DiscountRequests": "Demande de remise", + "Copylink": "Copier le lien", + "Disable": "Désactiver", + "Enable": "Activer", + "EnableSendEmail": "Activer l'envoi d'e-mail", + "SendEmail": "Envoyer un e-mail", + "SuccessfullyDisabled": "Désactivé avec succès", + "SuccessfullyEnabled": "Activé avec succès", + "EmailSent": "Email envoyé", + "SuccessfullySent": "Envoyé avec succès", + "SuccessfullyDeleted": "Supprimé avec succès", + "DiscountRequestDeletionWarningMessage": "La demande de remise sera supprimée", + "BusinessType": "Type d'entreprise", + "TotalQuestionCount": "Nombre total de questions", + "RemainingQuestionCount": "Nombre de questions restantes", + "TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount doit être supérieur à RemainingQuestionCount!", + "QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount et RemainingQuestionCount doivent être égaux à zéro ou supérieurs à zéro!", + "UnlimitedQuestionCount": "Nombre de questions illimité", + "Notes": "Remarques", + "Menu:Community": "Communauté", + "Menu:Articles": "Articles", + "Wait": "Attendez", + "Approve": "Approuver", + "Reject": "Rejeter", + "Details": "Détails", + "Url": "URL", + "Title": "Titre", + "ContentSource": "Source du contenu", + "Status": "Statut", + "ReadArticle": "Lire l'article", + "ArticleHasBeenWaiting": "L'article attendait", + "ArticleHasBeenApproved": "L'article a été approuvé", + "ArticleHasBeenRejected": "L'article a été rejeté", + "Permission:Community": "Communauté", + "Permission:CommunityArticle": "Article", + "Link": "Relier", + "Enum:ContentSource:0": "Github", + "Enum:ContentSource:1": "Externe", + "Enum:Status:0": "Attendre", + "Enum:Status:1": "Rejeté", + "Enum:Status:2": "Approuvé", + "Summary": "Résumé", + "AuthorName": "Nom de l'auteur", + "CoverImage": "Image de couverture", + "RemoveCacheConfirmationMessage": "Êtes-vous sûr de vouloir supprimer le cache de l'article \"{0}\"?", + "SuccessfullyRemoved": "Effacé avec succès", + "RemoveCache": "Supprimer le cache", + "Language": "Langue", + "Optional": "Optionnel", + "CreateArticleLanguageInfo": "La langue dans laquelle le message est rédigé", + "Enum:ContentSource:2": "Message vidéo", + "VideoPreview": "Aperçu vidéo", + "VideoPreviewErrorMessage": "L'URL de la vidéo donnée n'a pas pu être récupérée sur Youtube. Cela peut être dû au fait que la vidéo est privée ou que l'URL donnée n'est pas disponible.", + "DeleteCoverImage": "Supprimer l'image de couverture", + "DeleteCoverImageConfirmationMessage": "Voulez-vous vraiment supprimer l'image de couverture de \"{0}\"?", + "DeleteCoverImageSuccessMessage": "L'image de couverture a bien été supprimée", + "PaymentsOf": "Paiements de", + "ShowPaymentsOfOrganization": "Paiements", + "Date": "Date", + "Products": "Des produits", + "TotalAmount": "Montant total", + "Currency": "Devise", + "Gateway": "passerelle", + "State": "État", + "FailReason": "Raison de l'échec", + "ReIndexAllPosts": "Réindexer tous les messages", + "ReIndexAllPostsConfirmationMessage": "Voulez-vous vraiment réindexer tous les messages?", + "SuccessfullyReIndexAllPosts": "Tous les messages ont été réindexés avec succès.", + "Permission:FullSearch": "Recherche en texte intégral", + "Menu:CliAnalytics": "Cli Analytics", + "TemplateName": "Nom du modèle", + "TemplateVersion": "Version du modèle", + "DatabaseProvider": "Fournisseur de base de données", + "IsTiered": "Est hiérarchisé", + "ProjectName": "Nom du projet", + "Username": "Nom d'utilisateur", + "Tool": "Outil", + "Command": "Commander", + "UiFramework": "Framework de l'interface utilisateur", + "Options": "Options", + "CliAnalytics": "Cli Analytics", + "Permission:CliAnalyticses": "Analyses Cli", + "Permission:CliAnalytics": "Cli Analytics", + "Search": "Rechercher", + "ClearFilter": "Effacer le filtre", + "LicensePrivateKey": "Clé privée de licence", + "LicensePublicKey": "Clé publique de licence", + "ApiKey": "Clé d'API NuGet", + "ShowInvoiceRequestsOfOrganization": "Demandes de factures", + "ShowQuestionsOfOrganization": "Questions", + "Question": "Question", + "Open": "Ouvert", + "Questions": "Questions", + "InvoiceRequests": "Demandes de factures", + "Address": "Adresse", + "TaxNo": "Numéro de taxe", + "Permission:InvoiceRequest": "Demande de facturation", + "Permission:Question": "Question", + "AddNoteSuccessMessage": "Note ajoutée avec succès", + "NameSurname": "Prénom / nom de famille", + "Note": "Noter", + "Add": "Ajouter", + "ProjectDownloads": "Téléchargements de projets", + "ShowProjectDownloadsOfOrganization": "Téléchargements de projets", + "ShowAuditLogsOfOrganization": "Journaux d'audit", + "Enum:EntityChangeType:0": "Créé", + "Enum:EntityChangeType:1": "Mise à jour", + "Enum:EntityChangeType:2": "Supprimé", + "TenantId": "ID du souscrivant", + "ChangeTime": "Changer le temps", + "EntityTypeFullName": "Nom complet du type d'entité", + "AuditLogsFor{0}Organization": "Journaux d'audit pour l'organisation \"{0}\"", + "Permission:EntityChange": "Changement d'entité", + "Permission:ProjectDownload": "Télécharger le projet", + "Permission:PaymentRequest": "Demande de paiement", + "CreatorEmailAddress": "Adresse e-mail du créateur", + "EmailSendDate": "Date d'envoi de l'e-mail", + "PaymentRequestsFor{0}Organization": "Demandes de paiement pour l'organisation \"{0}\"", + "PaymentDetails": "Détails de paiement", + "PaymentProduct": "Produit de paiement", + "ProductName": "Nom du produit", + "Code": "Code", + "GenerateInvoice": "Générer une facture", + "ExportOrganizationsToExcel": "Exporter vers Excel", + "ThisExtensionIsNotAllowed": "Cette extension n'est pas autorisée.", + "TheFileIsTooLarge": "Le fichier est trop volumineux!", + "ArticleDeletionConfirmationMessage": "Voulez-vous vraiment supprimer définitivement cet article?", + "ChooseCoverImage": "Choisissez une image de couverture ..." + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hi.json new file mode 100644 index 0000000000..7b0f4ad205 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hi.json @@ -0,0 +1,282 @@ +{ + "culture": "hi", + "texts": { + "Permission:Organizations": "संगठनों", + "Permission:Manage": "संगठनों को प्रबंधित करें", + "Permission:DiscountRequests": "छूट का अनुरोध", + "Permission:DiscountManage": "डिस्काउंट अनुरोध प्रबंधित करें", + "Permission:Disable": "अक्षम", + "Permission:Enable": "सक्षम", + "Permission:EnableSendEmail": "ईमेल सक्षम करें", + "Permission:SendEmail": "ईमेल भेजें", + "Permission:NpmPackages": "एनपीएम पैकेज", + "Permission:NugetPackages": "नगेट संकुल", + "Permission:Maintenance": "रखरखाव", + "Permission:Maintain": "बनाए रखें", + "Permission:ClearCaches": "साफ कैश", + "Permission:Modules": "मॉड्यूल", + "Permission:Packages": "संकुल", + "Permission:Edit": "संपादित करें", + "Permission:Delete": "हटाएं", + "Permission:Create": "सृजन करना", + "Permission:Accounting": "लेखांकन", + "Permission:Accounting:Quotation": "उद्धरण", + "Permission:Accounting:Invoice": "बीजक", + "Menu:Organizations": "संगठनों", + "Menu:Accounting": "लेखांकन", + "Menu:Packages": "संकुल", + "Menu:DiscountRequests": "छूट का अनुरोध", + "NpmPackageDeletionWarningMessage": "यह NPM पैकेज हटा दिया जाएगा। क्या आप इसकी पुष्टि करते हैं?", + "NugetPackageDeletionWarningMessage": "यह नुगेट पैकेज हटा दिया जाएगा। क्या आप इसकी पुष्टि करते हैं?", + "ModuleDeletionWarningMessage": "यह मॉड्यूल हटा दिया जाएगा। क्या आप इसकी पुष्टि करते हैं?", + "Name": "नाम", + "DisplayName": "प्रदर्शित होने वाला नाम", + "ShortDescription": "संक्षिप्त वर्णन", + "NameFilter": "नाम", + "CreationTime": "रचना समय", + "IsPro": "समर्थक है", + "IsFreeToActiveLicenseOwners": "मालिकों को लाइसेंस देना मुफ्त", + "ShowOnModuleList": "मॉड्यूल सूची पर दिखाएं", + "EfCoreConfigureMethodName": "विधि नाम कॉन्फ़िगर करें", + "IsProFilter": "समर्थक है", + "ApplicationType": "आवेदन का प्रकार", + "Target": "लक्ष्य", + "TargetFilter": "लक्ष्य", + "ModuleClass": "मॉड्यूल वर्ग", + "NugetPackageTarget.DomainShared": "डोमेन साझा किया गया", + "NugetPackageTarget.Domain": "डोमेन", + "NugetPackageTarget.Application": "आवेदन", + "NugetPackageTarget.ApplicationContracts": "आवेदन संविदा", + "NugetPackageTarget.HttpApi": "Http Api", + "NugetPackageTarget.HttpApiClient": "Http Api क्लाइंट", + "NugetPackageTarget.Web": "वेब", + "NugetPackageTarget.EntityFrameworkCore": "DeleteAllEntityFramework Core", + "NugetPackageTarget.MongoDB": "MongoDB", + "Edit": "संपादित करें", + "Delete": "हटाएं", + "Refresh": "ताज़ा करना", + "NpmPackages": "एनपीएम पैकेज", + "NugetPackages": "नगेट संकुल", + "NpmPackageCount": "एनपीएम पैकेज की गणना", + "NugetPackageCount": "नगेट पैकेज गणना", + "Module": "मॉड्यूल", + "ModuleInfo": "मॉड्यूल जानकारी", + "CreateANpmPackage": "एक एनपीएम पैकेज बनाएँ", + "CreateAModule": "एक मॉड्यूल बनाएँ", + "CreateANugetPackage": "एक Nuget पैकेज बनाएँ", + "AddNew": "नया जोड़ें", + "PackageAlreadyExist{0}": "\"{0}\" पैकेज पहले से ही जोड़ा गया है।", + "ModuleAlreadyExist{0}": "\"{0}\" मॉड्यूल पहले से ही जोड़ा गया है।", + "ClearCache": "कैश को साफ़ करें", + "SuccessfullyCleared": "सफलतापूर्वक साफ़ हो गया", + "Menu:NpmPackages": "एनपीएम पैकेज", + "Menu:Modules": "मॉड्यूल", + "Menu:Maintenance": "रखरखाव", + "Menu:NugetPackages": "नगेट संकुल", + "CreateAnOrganization": "एक संगठन बनाएं", + "Organizations": "संगठनों", + "LongName": "लंबा नाम", + "LicenseType": "लाइसेंस के प्रकार", + "MissingLicenseTypeField": "लाइसेंस प्रकार क्षेत्र की आवश्यकता है!", + "LicenseStartTime": "लाइसेंस शुरू होने का समय", + "LicenseEndTime": "लाइसेंस समाप्ति का समय", + "AllowedDeveloperCount": "अनुमत डेवलपर गणना", + "UserNameOrEmailAddress": "उपयोगकर्ता का नाम या ईमेल पता", + "AddOwner": "मालिक जोड़ें", + "UserName": "उपयोगकर्ता नाम", + "Email": "ईमेल", + "Developers": "डेवलपर्स", + "AddDeveloper": "डेवलपर जोड़ें", + "Create": "सृजन करना", + "UserNotFound": "उपयोगकर्ता नहीं मिला", + "{0}WillBeRemovedFromDevelopers": "{0} डेवलपर्स से हटा दिया जाएगा, क्या आप पुष्टि करते हैं?", + "{0}WillBeRemovedFromOwners": "{0} मालिकों से हटा दिया जाएगा, क्या आप पुष्टि करते हैं?", + "{0}WillBeRemovedFromMembers": "{0} सदस्यों से हटा दिया जाएगा, क्या आप पुष्टि करते हैं?", + "Computers": "कंप्यूटर", + "UniqueComputerId": "यूनिक कंप्यूटर आई.डी.", + "LastSeenDate": "अंतिम बार देखी गई तारीख", + "{0}Computer{1}WillBeRemovedFromRecords": "{0} ({1}) का कंप्यूटर रिकॉर्ड से हटा दिया जाएगा", + "OrganizationDeletionWarningMessage": "संगठन को हटा दिया जाएगा", + "DeletingLastOwnerWarningMessage": "एक संगठन में कम से कम एक मालिक होना चाहिए! इसलिए आप इस स्वामी को नहीं निकाल सकते", + "This{0}AlreadyExistInThisOrganization": "यह {0} इस संगठन में पहले से मौजूद है", + "AreYouSureYouWantToDeleteAllComputers": "क्या आप वाकई सभी कंप्यूटर हटाना चाहते हैं?", + "DeleteAll": "सभी हटा दो", + "DoYouWantToCreateNewUser": "क्या आप नया उपयोगकर्ता बनाना चाहते हैं?", + "MasterModules": "मास्टर मॉड्यूल", + "OrganizationName": "संगठन का नाम", + "CreationDate": "निर्माण तिथि", + "LicenseStartDate": "लाइसेंस शुरू होने की तारीख", + "LicenseEndDate": "लाइसेंस की अंतिम तिथि", + "OrganizationNamePlaceholder": "संगठन का नाम...", + "TotalQuestionCountPlaceholder": "कुल प्रश्न संख्या ...", + "RemainingQuestionCountPlaceholder": "शेष प्रश्न गणना ...", + "LicenseTypePlaceholder": "लाइसेंस के प्रकार...", + "CreationDatePlaceholder": "निर्माण तिथि...", + "LicenseStartDatePlaceholder": "लाइसेंस शुरू होने की तारीख ...", + "LicenseEndDatePlaceholder": "लाइसेंस की अंतिम तिथि ...", + "UsernameOrEmail": "उपयोगकर्ता का नाम या ईमेल", + "UsernameOrEmailPlaceholder": "उपयोगकर्ता का नाम या ईमेल...", + "Member": "सदस्य", + "PurchaseOrderNo": "खरीद आदेश ्संक्या", + "QuotationDate": "बोली की तारीख", + "CompanyName": "कंपनी का नाम", + "CompanyAddress": "कम्पनी का पता", + "Price": "कीमत", + "DiscountText": "डिस्काउंट पाठ", + "DiscountQuantity": "छूट मात्रा", + "DiscountPrice": "डिस्काउंट कीमत", + "Quotation": "उद्धरण", + "ExtraText": "अतिरिक्त पाठ", + "ExtraAmount": "अतिरिक्त राशि", + "DownloadQuotation": "उद्धरण डाउनलोड करें", + "Invoice": "बीजक", + "TaxNumber": "कर संख्या", + "InvoiceNumber": "बीजक संख्या", + "InvoiceDate": "चालान की तारीख", + "InvoiceNote": "चालान नोट", + "Quantity": "मात्रा", + "AddProduct": "उत्पाद जोड़ें", + "AddProductWarning": "आपको उत्पाद जोड़ने की आवश्यकता है!", + "TotalPrice": "कुल कीमत", + "Generate": "उत्पन्न", + "MissingQuantityField": "मात्रा फ़ील्ड आवश्यक है!", + "MissingPriceField": "मूल्य क्षेत्र की आवश्यकता है!", + "CodeUsageStatus": "स्थिति", + "Country": "देश", + "DeveloperCount": "डेवलपर गणना", + "RequestCode": "अनुरोध कोड", + "WebSite": "वेबसाइट", + "GithubUsername": "Github उपयोगकर्ता नाम", + "PhoneNumber": "फ़ोन नंबर", + "ProjectDescription": "परियोजना विवरण", + "Referrer": "संदर्भ", + "DiscountRequests": "छूट का अनुरोध", + "Copylink": "प्रतिरूप जोड़ना", + "Disable": "अक्षम", + "Enable": "सक्षम", + "EnableSendEmail": "ईमेल सक्षम करें", + "SendEmail": "ईमेल भेजें", + "SuccessfullyDisabled": "सफलतापूर्वक अक्षम किया गया", + "SuccessfullyEnabled": "सफलतापूर्वक सक्षम किया गया", + "EmailSent": "ईमेल भेजा", + "SuccessfullySent": "सफलतापूर्वक भेजा", + "SuccessfullyDeleted": "सफलतापूर्वक हटा दिया गया", + "DiscountRequestDeletionWarningMessage": "छूट अनुरोध हटा दिया जाएगा", + "BusinessType": "व्यापार के प्रकार", + "TotalQuestionCount": "कुल प्रश्न संख्या", + "RemainingQuestionCount": "शेष प्रश्न गणना", + "TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount RemainingQuestionCount से अधिक होना चाहिए!", + "QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount और RemainingQuestionCount शून्य या शून्य से अधिक होना चाहिए!", + "UnlimitedQuestionCount": "असीमित प्रश्न गणना", + "Notes": "टिप्पणियाँ", + "Menu:Community": "समुदाय", + "Menu:Articles": "सामग्री", + "Wait": "रुको", + "Approve": "मंजूर", + "Reject": "अस्वीकार", + "Details": "विवरण", + "Url": "यूआरएल", + "Title": "शीर्षक", + "ContentSource": "विषय - वस्तु का स्रोत", + "Status": "स्थिति", + "ReadArticle": "लेख पढ़ें", + "ArticleHasBeenWaiting": "लेख की प्रतीक्षा रही", + "ArticleHasBeenApproved": "अनुच्छेद स्वीकृत किया गया है", + "ArticleHasBeenRejected": "अनुच्छेद अस्वीकार कर दिया गया है", + "Permission:Community": "समुदाय", + "Permission:CommunityArticle": "लेख", + "Link": "संपर्क", + "Enum:ContentSource:0": "Github", + "Enum:ContentSource:1": "बाहरी", + "Enum:Status:0": "इंतज़ार कर रही", + "Enum:Status:1": "अस्वीकृत", + "Enum:Status:2": "मंजूर की", + "Summary": "सारांश", + "AuthorName": "लेखक का नाम", + "CoverImage": "कवर छवि", + "RemoveCacheConfirmationMessage": "क्या आप वाकई \"{0}\" लेख के लिए कैश निकालना चाहते हैं?", + "SuccessfullyRemoved": "सफलतापूर्वक साफ़ हो गया", + "RemoveCache": "कैश निकालें", + "Language": "भाषा: हिन्दी", + "Optional": "ऐच्छिक", + "CreateArticleLanguageInfo": "वह भाषा जिसमें पद लिखा जाता है", + "Enum:ContentSource:2": "वीडियो पोस्ट", + "VideoPreview": "वीडियो पूर्वावलोकन", + "VideoPreviewErrorMessage": "दिया गया वीडियो url Youtube से पुनः प्राप्त नहीं कर सका। यह वीडियो निजी होने के कारण हो सकता है या दिया गया URL उपलब्ध नहीं है।", + "DeleteCoverImage": "कवर छवि हटाएं", + "DeleteCoverImageConfirmationMessage": "क्या आप वाकई \"{0}\" के लिए कवर छवि को हटाना चाहते हैं?", + "DeleteCoverImageSuccessMessage": "कवर छवि सफलतापूर्वक हटा दी गई", + "PaymentsOf": "के भुगतान", + "ShowPaymentsOfOrganization": "भुगतान", + "Date": "तारीख", + "Products": "उत्पादों", + "TotalAmount": "कुल रकम", + "Currency": "मुद्रा", + "Gateway": "द्वार", + "State": "राज्य", + "FailReason": "विफल कारण", + "ReIndexAllPosts": "सभी पदों को फिर से लिखना", + "ReIndexAllPostsConfirmationMessage": "क्या आप वाकई सभी पदों को पुनः प्राप्त करना चाहते हैं?", + "SuccessfullyReIndexAllPosts": "सभी पदों को सफलतापूर्वक रीइंसेक्स किया गया है।", + "Permission:FullSearch": "पूरा पाठ खोजें", + "Menu:CliAnalytics": "Cli Analytics", + "TemplateName": "टेम्पलेट नाम", + "TemplateVersion": "टेम्पलेट संस्करण", + "DatabaseProvider": "डेटाबेस प्रदाता", + "IsTiered": "तीयर है", + "ProjectName": "परियोजना का नाम", + "Username": "उपयोगकर्ता नाम", + "Tool": "साधन", + "Command": "आदेश", + "UiFramework": "उई ढांचा", + "Options": "विकल्प", + "CliAnalytics": "Cli Analytics", + "Permission:CliAnalyticses": "क्ली एनालिटिक्स", + "Permission:CliAnalytics": "Cli Analytics", + "Search": "खोज", + "ClearFilter": "स्पष्ट निस्यंदक", + "LicensePrivateKey": "लाइसेंस निजी कुंजी", + "LicensePublicKey": "लाइसेंस सार्वजनिक कुंजी", + "ApiKey": "NuGet एपीआई कुंजी", + "ShowInvoiceRequestsOfOrganization": "चालान अनुरोध", + "ShowQuestionsOfOrganization": "प्रशन", + "Question": "सवाल", + "Open": "खुला हुआ", + "Questions": "प्रशन", + "InvoiceRequests": "चालान अनुरोध", + "Address": "पता", + "TaxNo": "टैक्स संख्या", + "Permission:InvoiceRequest": "बिल के लिए अनुरोध", + "Permission:Question": "सवाल", + "AddNoteSuccessMessage": "नोट सफलतापूर्वक जोड़ा गया", + "NameSurname": "नाम सरनेम", + "Note": "ध्यान दें", + "Add": "जोड़ना", + "ProjectDownloads": "प्रोजेक्ट डाउनलोड", + "ShowProjectDownloadsOfOrganization": "प्रोजेक्ट डाउनलोड", + "ShowAuditLogsOfOrganization": "ऑडिट लॉग", + "Enum:EntityChangeType:0": "बनाया था", + "Enum:EntityChangeType:1": "अद्यतन", + "Enum:EntityChangeType:2": "हटाए गए", + "TenantId": "किरायेदार आईडी", + "ChangeTime": "समय परिवर्तन करें", + "EntityTypeFullName": "संपूर्ण प्रकार पूर्ण नाम", + "AuditLogsFor{0}Organization": "\"{0}\" संगठन के लिए ऑडिट लॉग", + "Permission:EntityChange": "इकाई परिवर्तन", + "Permission:ProjectDownload": "प्रोजेक्ट डाउनलोड", + "Permission:PaymentRequest": "भुगतान अनुरोध", + "CreatorEmailAddress": "निर्माता का ईमेल पता", + "EmailSendDate": "ईमेल भेजने की तारीख", + "PaymentRequestsFor{0}Organization": "\"{0}\" संगठन के लिए भुगतान अनुरोध", + "PaymentDetails": "भुगतान विवरण", + "PaymentProduct": "भुगतान उत्पाद", + "ProductName": "उत्पाद का नाम", + "Code": "कोड", + "GenerateInvoice": "आनंद उत्पन्न करें", + "ExportOrganizationsToExcel": "एक्सेल में भेजे", + "ThisExtensionIsNotAllowed": "इस एक्सटेंशन की अनुमति नहीं है।", + "TheFileIsTooLarge": "फ़ाइल बहुत बड़ी है!", + "ArticleDeletionConfirmationMessage": "क्या आप वाकई इस लेख को हटाना चाहते हैं?", + "ChooseCoverImage": "कवर छवि चुनें ..." + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/it.json new file mode 100644 index 0000000000..2aaacd7b86 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/it.json @@ -0,0 +1,282 @@ +{ + "culture": "it", + "texts": { + "Permission:Organizations": "Organizzazioni", + "Permission:Manage": "Gestisci organizzazioni", + "Permission:DiscountRequests": "Richieste di sconto", + "Permission:DiscountManage": "Gestisci le richieste di sconto", + "Permission:Disable": "disattivare", + "Permission:Enable": "Abilitare", + "Permission:EnableSendEmail": "Abilita Invia e-mail", + "Permission:SendEmail": "Invia una email", + "Permission:NpmPackages": "Pacchetti NPM", + "Permission:NugetPackages": "Pacchetti Nuget", + "Permission:Maintenance": "Manutenzione", + "Permission:Maintain": "Mantenere", + "Permission:ClearCaches": "Cancella cache", + "Permission:Modules": "Moduli", + "Permission:Packages": "Pacchi", + "Permission:Edit": "modificare", + "Permission:Delete": "Elimina", + "Permission:Create": "Creare", + "Permission:Accounting": "Contabilità", + "Permission:Accounting:Quotation": "Quotazione", + "Permission:Accounting:Invoice": "Fattura", + "Menu:Organizations": "Organizzazioni", + "Menu:Accounting": "Contabilità", + "Menu:Packages": "Pacchi", + "Menu:DiscountRequests": "Richieste di sconto", + "NpmPackageDeletionWarningMessage": "Questo pacchetto NPM verrà eliminato. Lo confermi?", + "NugetPackageDeletionWarningMessage": "Questo pacchetto Nuget verrà eliminato. Lo confermi?", + "ModuleDeletionWarningMessage": "Questo modulo verrà eliminato. Lo confermi?", + "Name": "Nome", + "DisplayName": "Nome da visualizzare", + "ShortDescription": "Breve descrizione", + "NameFilter": "Nome", + "CreationTime": "Tempo di creazione", + "IsPro": "È pro", + "IsFreeToActiveLicenseOwners": "Gratuito per i proprietari di licenze", + "ShowOnModuleList": "Mostra nell'elenco dei moduli", + "EfCoreConfigureMethodName": "Configurare il nome del metodo", + "IsProFilter": "È pro", + "ApplicationType": "Tipo di applicazione", + "Target": "Bersaglio", + "TargetFilter": "Bersaglio", + "ModuleClass": "Classe del modulo", + "NugetPackageTarget.DomainShared": "Dominio condiviso", + "NugetPackageTarget.Domain": "Dominio", + "NugetPackageTarget.Application": "Applicazione", + "NugetPackageTarget.ApplicationContracts": "Contratti applicativi", + "NugetPackageTarget.HttpApi": "Http Api", + "NugetPackageTarget.HttpApiClient": "Client API HTTP", + "NugetPackageTarget.Web": "ragnatela", + "NugetPackageTarget.EntityFrameworkCore": "DeleteAllEntityFramework Core", + "NugetPackageTarget.MongoDB": "MongoDB", + "Edit": "modificare", + "Delete": "Elimina", + "Refresh": "ricaricare", + "NpmPackages": "Pacchetti NPM", + "NugetPackages": "Pacchetti Nuget", + "NpmPackageCount": "Conteggio pacchetti NPM", + "NugetPackageCount": "Conteggio pacchetti Nuget", + "Module": "Moduli", + "ModuleInfo": "Informazioni sul modulo", + "CreateANpmPackage": "Crea un pacchetto NPM", + "CreateAModule": "Crea un modulo", + "CreateANugetPackage": "Crea un pacchetto Nuget", + "AddNew": "Aggiungere nuova", + "PackageAlreadyExist{0}": "Il pacchetto \"{0}\" è già aggiunto.", + "ModuleAlreadyExist{0}": "Il modulo \"{0}\" è già aggiunto.", + "ClearCache": "Cancella cache", + "SuccessfullyCleared": "Cancellato con successo", + "Menu:NpmPackages": "Pacchetti NPM", + "Menu:Modules": "Moduli", + "Menu:Maintenance": "Manutenzione", + "Menu:NugetPackages": "Pacchetti Nuget", + "CreateAnOrganization": "Crea un'organizzazione", + "Organizations": "Organizzazioni", + "LongName": "Nome lungo", + "LicenseType": "Tipo di licenza", + "MissingLicenseTypeField": "Il campo del tipo di licenza è obbligatorio!", + "LicenseStartTime": "Ora di inizio della licenza", + "LicenseEndTime": "Ora di fine della licenza", + "AllowedDeveloperCount": "Conteggio sviluppatori consentito", + "UserNameOrEmailAddress": "Username o Indirizzo Email", + "AddOwner": "Aggiungi proprietario", + "UserName": "Nome utente", + "Email": "E-mail", + "Developers": "Sviluppatori", + "AddDeveloper": "Aggiungi sviluppatore", + "Create": "Creare", + "UserNotFound": "Utente non trovato", + "{0}WillBeRemovedFromDevelopers": "{0} Verrà rimosso dagli sviluppatori, confermi?", + "{0}WillBeRemovedFromOwners": "{0} Verrà rimosso dai proprietari, confermi?", + "{0}WillBeRemovedFromMembers": "{0} Verrà rimosso dai membri, confermi?", + "Computers": "Computer", + "UniqueComputerId": "ID computer univoco", + "LastSeenDate": "Data dell'ultimo accesso", + "{0}Computer{1}WillBeRemovedFromRecords": "Il computer di {0} ({1}) verrà rimosso dai record", + "OrganizationDeletionWarningMessage": "L'organizzazione verrà eliminata", + "DeletingLastOwnerWarningMessage": "Un'organizzazione deve avere almeno un proprietario! Pertanto non puoi rimuovere questo proprietario", + "This{0}AlreadyExistInThisOrganization": "Questo {0} esiste già in questa organizzazione", + "AreYouSureYouWantToDeleteAllComputers": "Sei sicuro di voler eliminare tutti i computer?", + "DeleteAll": "Cancella tutto", + "DoYouWantToCreateNewUser": "Vuoi creare un nuovo utente?", + "MasterModules": "Moduli master", + "OrganizationName": "Nome dell'organizzazione", + "CreationDate": "Data di creazione", + "LicenseStartDate": "Data di inizio della licenza", + "LicenseEndDate": "Data di fine della licenza", + "OrganizationNamePlaceholder": "Nome dell'organizzazione...", + "TotalQuestionCountPlaceholder": "Conteggio totale delle domande ...", + "RemainingQuestionCountPlaceholder": "Numero di domande rimanenti ...", + "LicenseTypePlaceholder": "Tipo di licenza...", + "CreationDatePlaceholder": "Data di creazione...", + "LicenseStartDatePlaceholder": "Data di inizio della licenza ...", + "LicenseEndDatePlaceholder": "Data di fine della licenza ...", + "UsernameOrEmail": "Nome utente o email", + "UsernameOrEmailPlaceholder": "Nome utente o email...", + "Member": "Membro", + "PurchaseOrderNo": "Ordine d'Acquisto N °", + "QuotationDate": "Data di quotazione", + "CompanyName": "Nome della ditta", + "CompanyAddress": "Indirizzo aziendale", + "Price": "Prezzo", + "DiscountText": "Testo di sconto", + "DiscountQuantity": "Quantità di sconto", + "DiscountPrice": "Prezzo scontato", + "Quotation": "Quotazione", + "ExtraText": "Testo extra", + "ExtraAmount": "Importo extra", + "DownloadQuotation": "Scarica preventivo", + "Invoice": "Fattura", + "TaxNumber": "Codice fiscale", + "InvoiceNumber": "Numero di fattura", + "InvoiceDate": "Data fattura", + "InvoiceNote": "Nota fattura", + "Quantity": "Quantità", + "AddProduct": "Aggiungi prodotto", + "AddProductWarning": "Devi aggiungere il prodotto!", + "TotalPrice": "Prezzo totale", + "Generate": "creare", + "MissingQuantityField": "Il campo della quantità è obbligatorio!", + "MissingPriceField": "Il campo Prezzo è obbligatorio!", + "CodeUsageStatus": "Stato", + "Country": "Nazione", + "DeveloperCount": "Conteggio sviluppatori", + "RequestCode": "Codice richiesto", + "WebSite": "Sito web", + "GithubUsername": "Nome utente GitHub", + "PhoneNumber": "Numero di telefono", + "ProjectDescription": "descrizione del progetto", + "Referrer": "Referrer", + "DiscountRequests": "Richiesta di sconto", + "Copylink": "Copia link", + "Disable": "disattivare", + "Enable": "Abilitare", + "EnableSendEmail": "Abilita Invia e-mail", + "SendEmail": "Invia una email", + "SuccessfullyDisabled": "Disabilitato con successo", + "SuccessfullyEnabled": "Abilitato con successo", + "EmailSent": "Email inviata", + "SuccessfullySent": "Inviato con successo", + "SuccessfullyDeleted": "Eliminato con successo", + "DiscountRequestDeletionWarningMessage": "La richiesta di sconto verrà eliminata", + "BusinessType": "tipo di affari", + "TotalQuestionCount": "Conteggio totale delle domande", + "RemainingQuestionCount": "Numero di domande rimanenti", + "TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount deve essere maggiore di RemainingQuestionCount!", + "QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount e RemainingQuestionCount devono essere zero o maggiori di zero!", + "UnlimitedQuestionCount": "Conteggio illimitato delle domande", + "Notes": "Appunti", + "Menu:Community": "Comunità", + "Menu:Articles": "Articoli", + "Wait": "Aspettare", + "Approve": "Approvare", + "Reject": "Rifiutare", + "Details": "Dettagli", + "Url": "Url", + "Title": "Titolo", + "ContentSource": "Fonte di contenuto", + "Status": "Stato", + "ReadArticle": "Leggi l'articolo", + "ArticleHasBeenWaiting": "L'articolo è stato in attesa", + "ArticleHasBeenApproved": "L'articolo è stato approvato", + "ArticleHasBeenRejected": "L'articolo è stato respinto", + "Permission:Community": "Comunità", + "Permission:CommunityArticle": "Articolo", + "Link": "Link", + "Enum:ContentSource:0": "Github", + "Enum:ContentSource:1": "Esterno", + "Enum:Status:0": "In attesa", + "Enum:Status:1": "Respinto", + "Enum:Status:2": "Approvato", + "Summary": "Sommario", + "AuthorName": "Nome dell'autore", + "CoverImage": "Immagine di copertina", + "RemoveCacheConfirmationMessage": "Sei sicuro di aver rimosso la cache per l'articolo \"{0}\"?", + "SuccessfullyRemoved": "Cancellato con successo", + "RemoveCache": "Rimuovi cache", + "Language": "linguaggio", + "Optional": "Opzionale", + "CreateArticleLanguageInfo": "La lingua in cui è scritto il post", + "Enum:ContentSource:2": "Post video", + "VideoPreview": "Anteprima video", + "VideoPreviewErrorMessage": "Impossibile recuperare l'URL del video da Youtube. Ciò può essere causato dal fatto che il video è privato o l'URL fornito non è disponibile.", + "DeleteCoverImage": "Elimina immagine di copertina", + "DeleteCoverImageConfirmationMessage": "Sei sicuro di voler eliminare l'immagine di copertina per \"{0}\"?", + "DeleteCoverImageSuccessMessage": "Immagine di copertina eliminata con successo", + "PaymentsOf": "Pagamenti di", + "ShowPaymentsOfOrganization": "Pagamenti", + "Date": "Data", + "Products": "Prodotti", + "TotalAmount": "Importo totale", + "Currency": "Moneta", + "Gateway": "Gateway", + "State": "Stato", + "FailReason": "Motivo fallito", + "ReIndexAllPosts": "Reindicizza tutti i post", + "ReIndexAllPostsConfirmationMessage": "Sei sicuro di voler reindicizzare tutti i post?", + "SuccessfullyReIndexAllPosts": "Tutti i post sono stati reindicizzati con successo.", + "Permission:FullSearch": "Ricerca nel testo completo", + "Menu:CliAnalytics": "Cli Analytics", + "TemplateName": "Nome modello", + "TemplateVersion": "Versione modello", + "DatabaseProvider": "Provider di database", + "IsTiered": "È a livelli", + "ProjectName": "Nome del progetto", + "Username": "Nome utente", + "Tool": "Attrezzo", + "Command": "Comando", + "UiFramework": "Framework dell'interfaccia utente", + "Options": "Opzioni", + "CliAnalytics": "Cli Analytics", + "Permission:CliAnalyticses": "Cli Analyticses", + "Permission:CliAnalytics": "Cli Analytics", + "Search": "Ricerca", + "ClearFilter": "Filtro pulito", + "LicensePrivateKey": "Chiave privata della licenza", + "LicensePublicKey": "Licenza chiave pubblica", + "ApiKey": "Chiave API NuGet", + "ShowInvoiceRequestsOfOrganization": "Richieste di fattura", + "ShowQuestionsOfOrganization": "Domande", + "Question": "Domanda", + "Open": "Aperto", + "Questions": "Domande", + "InvoiceRequests": "Richieste di fattura", + "Address": "Indirizzo", + "TaxNo": "No fiscale", + "Permission:InvoiceRequest": "Richiesta di fattura", + "Permission:Question": "Domanda", + "AddNoteSuccessMessage": "Nota aggiunta con successo", + "NameSurname": "Nome cognome", + "Note": "Nota", + "Add": "Inserisci", + "ProjectDownloads": "Download del progetto", + "ShowProjectDownloadsOfOrganization": "Download del progetto", + "ShowAuditLogsOfOrganization": "Registri di controllo", + "Enum:EntityChangeType:0": "Creato", + "Enum:EntityChangeType:1": "Aggiornato", + "Enum:EntityChangeType:2": "Eliminato", + "TenantId": "ID inquilino", + "ChangeTime": "Cambia il tempo", + "EntityTypeFullName": "Nome completo del tipo di entità", + "AuditLogsFor{0}Organization": "Log di controllo per l'organizzazione \"{0}\"", + "Permission:EntityChange": "Modifica entità", + "Permission:ProjectDownload": "Download del progetto", + "Permission:PaymentRequest": "Richiesta di pagamento", + "CreatorEmailAddress": "Indirizzo email del creatore", + "EmailSendDate": "Data di invio dell'e-mail", + "PaymentRequestsFor{0}Organization": "Richieste di pagamento per l'organizzazione \"{0}\"", + "PaymentDetails": "Dettagli di pagamento", + "PaymentProduct": "Prodotto di pagamento", + "ProductName": "nome del prodotto", + "Code": "Codice", + "GenerateInvoice": "Genera fattura", + "ExportOrganizationsToExcel": "esportare in Excel", + "ThisExtensionIsNotAllowed": "Questa estensione non è consentita.", + "TheFileIsTooLarge": "Il file è troppo grande!", + "ArticleDeletionConfirmationMessage": "Sei sicuro di voler eliminare definitivamente questo articolo?", + "ChooseCoverImage": "Scegli un'immagine di copertina ..." + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json index 531e0424d4..c1253db259 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json @@ -221,6 +221,12 @@ "PaymentProduct": "Ödeme Ürünü", "ProductName": "Ürün İsmi", "Code": "Kod", - "GenerateInvoice": "Fatura Oluştur" + "GenerateInvoice": "Fatura Oluştur", + "ExportOrganizationsToExcel": "Excel'e aktar", + "ThisExtensionIsNotAllowed": "Bu uzantıya izin verilmiyor.", + "TheFileIsTooLarge": "Dosya çok büyük.", + "ArticleDeletionConfirmationMessage": "Bu makaleyi kalıcı olarak silmek istediğinizden emin misiniz?", + "ChooseCoverImage": "Bir kapak resmi seçin...", + "CoverImage": "Kapak Resmi" } -} \ No newline at end of file +} diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json index a027bd3699..40cd64838c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json @@ -256,6 +256,11 @@ "PaymentProduct": "付款产品", "ProductName": "产品名称", "Code": "代码", - "GenerateInvoice": "生成发票" + "GenerateInvoice": "生成发票", + "ExportOrganizationsToExcel": "将组织导出到Excel", + "ThisExtensionIsNotAllowed": "不允许此扩展名.", + "TheFileIsTooLarge": "文件过大.", + "ArticleDeletionConfirmationMessage": "您确定要硬删除这篇文章吗?", + "ChooseCoverImage": "选项一张封面图片" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json new file mode 100644 index 0000000000..c5cac6d63c --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json @@ -0,0 +1,37 @@ +{ + "culture": "fi", + "texts": { + "Volo.AbpIo.Domain:010004": "Jäsenmäärä on saavutettu!", + "Volo.AbpIo.Domain:010005": "Omistajien enimmäismäärä saavutettu!", + "Volo.AbpIo.Domain:010006": "Tämä käyttäjä on jo tämän organisaation omistaja!", + "Volo.AbpIo.Domain:010007": "Tämä käyttäjä on jo kehittäjä tässä organisaatiossa!", + "Volo.AbpIo.Domain:010008": "Sallittu kehittäjien määrä ei voi olla pienempi kuin nykyinen kehittäjien määrä!", + "Volo.AbpIo.Domain:010009": "Sallittu kehittäjien määrä ei voi olla pienempi kuin 0!", + "Volo.AbpIo.Domain:010010": "Mac-osoitteiden enimmäismäärä on ylitetty!", + "Volo.AbpIo.Domain:010011": "Henkilökohtaisella lisenssillä voi olla enintään yksi kehittäjä!", + "Volo.AbpIo.Domain:010012": "Lisenssiä ei voida pidentää kuukauden kuluttua lisenssin päättymisestä!", + "Volo.AbpIo.Domain:020001": "Tätä NPM-pakettia ei voitu poistaa, koska \"{NugetPackages}\" Nuget-paketit ovat riippuvaisia tästä paketista.", + "Volo.AbpIo.Domain:020002": "Tätä NPM-pakettia ei voitu poistaa, koska moduulit \"{Modules}\" käyttävät tätä pakettia.", + "Volo.AbpIo.Domain:020003": "Tätä NPM-pakettia ei voitu poistaa, koska moduulit \"{Modules}\" käyttävät tätä pakettia ja \"{NugetPackages}\" -nugettipaketit ovat riippuvaisia tästä paketista.", + "Volo.AbpIo.Domain:020004": "Tätä Nuget-pakettia ei voitu poistaa, koska moduulit \"{Modules}\" käyttävät tätä pakettia.", + "WantToLearn?": "Haluan oppia?", + "ReadyToGetStarted?": "Oletko valmis aloittamaan?", + "JoinOurCommunity": "Liity yhteisöömme", + "GetStartedUpper": "ALOITTAA", + "ForkMeOnGitHub": "Haaraa minut GitHubiin", + "Features": "ominaisuudet", + "GetStarted": "Aloittaa", + "Documents": "Asiakirjat", + "Community": "Yhteisö", + "ContributionGuide": "Contribution Guide", + "Blog": "Blogi", + "Commercial": "Kaupallinen", + "MyAccount": "Tilini", + "Permission:License": "Lisenssi", + "Permission:UserInfo": "Käyttäjän tiedot", + "SeeDocuments": "Katso Asiakirjat", + "Samples": "Näytteet", + "Framework": "Kehys", + "Support": "Tuki" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fr.json new file mode 100644 index 0000000000..c50d28f13a --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fr.json @@ -0,0 +1,37 @@ +{ + "culture": "fr", + "texts": { + "Volo.AbpIo.Domain:010004": "Nombre maximum de membres atteint!", + "Volo.AbpIo.Domain:010005": "Nombre maximum de propriétaires atteint!", + "Volo.AbpIo.Domain:010006": "Cet utilisateur est déjà propriétaire de cette organisation!", + "Volo.AbpIo.Domain:010007": "Cet utilisateur est déjà développeur dans cette organisation!", + "Volo.AbpIo.Domain:010008": "Le nombre de développeurs autorisé ne peut pas être inférieur au nombre de développeurs actuel!", + "Volo.AbpIo.Domain:010009": "Le nombre de développeurs autorisé ne peut pas être inférieur à 0!", + "Volo.AbpIo.Domain:010010": "Le nombre maximal d'adresses Mac est dépassé!", + "Volo.AbpIo.Domain:010011": "La licence personnelle ne peut pas avoir plus d'un développeur!", + "Volo.AbpIo.Domain:010012": "La licence ne peut pas être prolongée un mois après l'expiration de la licence!", + "Volo.AbpIo.Domain:020001": "Impossible de supprimer ce package NPM car les packages Nuget \"{NugetPackages}\" dépendent de ce package.", + "Volo.AbpIo.Domain:020002": "Impossible de supprimer ce package NPM car les modules \"{Modules}\" utilisent ce package.", + "Volo.AbpIo.Domain:020003": "Impossible de supprimer ce package NPM car les modules \"{Modules}\" utilisent ce package et les packages Nuget \"{NugetPackages}\" dépendent de ce package.", + "Volo.AbpIo.Domain:020004": "Impossible de supprimer ce package Nuget car les modules \"{Modules}\" utilisent ce package.", + "WantToLearn?": "Vous voulez apprendre?", + "ReadyToGetStarted?": "Prêt à commencer?", + "JoinOurCommunity": "Rejoignez notre communauté", + "GetStartedUpper": "COMMENCER", + "ForkMeOnGitHub": "Fork moi sur GitHub", + "Features": "Caractéristiques", + "GetStarted": "Commencer", + "Documents": "Des documents", + "Community": "Communauté", + "ContributionGuide": "Guide de contribution", + "Blog": "Blog", + "Commercial": "Commercial", + "MyAccount": "Mon compte", + "Permission:License": "Licence", + "Permission:UserInfo": "Informations sur l'utilisateur", + "SeeDocuments": "Voir les documents", + "Samples": "Échantillons", + "Framework": "Cadre", + "Support": "Support" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json new file mode 100644 index 0000000000..cd1ec4491d --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json @@ -0,0 +1,37 @@ +{ + "culture": "hi", + "texts": { + "Volo.AbpIo.Domain:010004": "अधिकतम सदस्य संख्या तक पहुँच गया!", + "Volo.AbpIo.Domain:010005": "अधिकतम मालिक की गिनती तक पहुँच गया!", + "Volo.AbpIo.Domain:010006": "यह उपयोगकर्ता पहले से ही इस संगठन का मालिक है!", + "Volo.AbpIo.Domain:010007": "यह उपयोगकर्ता इस संगठन में पहले से ही एक डेवलपर है!", + "Volo.AbpIo.Domain:010008": "अनुमत डेवलपर गणना कम नहीं हो सकती है तो वर्तमान डेवलपर गणना!", + "Volo.AbpIo.Domain:010009": "अनुमत डेवलपर गणना 0 से कम नहीं हो सकती है!", + "Volo.AbpIo.Domain:010010": "अधिकतम मैक पता गणना पार हो गई है!", + "Volo.AbpIo.Domain:010011": "व्यक्तिगत लाइसेंस में 1 से अधिक डेवलपर नहीं हो सकते हैं!", + "Volo.AbpIo.Domain:010012": "लाइसेंस की अवधि समाप्त होने के एक महीने बाद तक लाइसेंस नहीं बढ़ाया जा सकता है!", + "Volo.AbpIo.Domain:020001": "इस NPM पैकेज को नहीं हटाया जा सका क्योंकि \"{NugetPackages}\" नुगेट पैकेज इस पैकेज पर निर्भर हैं।", + "Volo.AbpIo.Domain:020002": "यह NPM पैकेज नहीं हटा सका क्योंकि \"{मॉड्यूल}\" मॉड्यूल इस पैकेज का उपयोग कर रहे हैं।", + "Volo.AbpIo.Domain:020003": "इस NPM पैकेज को नहीं हटाया जा सका क्योंकि \"{मॉड्यूल}\" मॉड्यूल इस पैकेज का उपयोग कर रहे हैं और \"{NugetPackages}\" नुगेट पैकेज इस पैकेज पर निर्भर हैं।", + "Volo.AbpIo.Domain:020004": "इस Nuget पैकेज को हटाया नहीं जा सका क्योंकि \"{Modules}\" मॉड्यूल इस पैकेज का उपयोग कर रहे हैं।", + "WantToLearn?": "सीखना चाहते है?", + "ReadyToGetStarted?": "आरंभ करने के लिए तैयार हैं?", + "JoinOurCommunity": "हमारी संस्था से जुड़े", + "GetStartedUpper": "शुरू हो जाओ", + "ForkMeOnGitHub": "GitHub पर मेरे कांटा", + "Features": "विशेषताएं", + "GetStarted": "शुरू हो जाओ", + "Documents": "दस्तावेज़", + "Community": "समुदाय", + "ContributionGuide": "योगदान गाइड", + "Blog": "ब्लॉग", + "Commercial": "व्यावसायिक", + "MyAccount": "मेरा खाता", + "Permission:License": "लाइसेंस", + "Permission:UserInfo": "हमें जानकारी", + "SeeDocuments": "दस्तावेज़ देखें", + "Samples": "नमूने", + "Framework": "ढांचा", + "Support": "सहयोग" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/it.json new file mode 100644 index 0000000000..8a0e9d9e0b --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/it.json @@ -0,0 +1,37 @@ +{ + "culture": "it", + "texts": { + "Volo.AbpIo.Domain:010004": "Numero massimo di membri raggiunto!", + "Volo.AbpIo.Domain:010005": "Numero massimo di proprietari raggiunto!", + "Volo.AbpIo.Domain:010006": "Questo utente è già proprietario di questa organizzazione!", + "Volo.AbpIo.Domain:010007": "Questo utente è già uno sviluppatore in questa organizzazione!", + "Volo.AbpIo.Domain:010008": "Il numero di sviluppatori consentito non può essere inferiore al numero di sviluppatori corrente!", + "Volo.AbpIo.Domain:010009": "Il numero di sviluppatori consentito non può essere inferiore a 0!", + "Volo.AbpIo.Domain:010010": "Il numero massimo di indirizzi mac è stato superato!", + "Volo.AbpIo.Domain:010011": "La licenza personale non può avere più di 1 sviluppatore!", + "Volo.AbpIo.Domain:010012": "La licenza non può essere estesa un mese dopo la scadenza della licenza!", + "Volo.AbpIo.Domain:020001": "Impossibile eliminare questo pacchetto NPM perché i pacchetti Nuget \"{NugetPackages}\" dipendono da questo pacchetto.", + "Volo.AbpIo.Domain:020002": "Impossibile eliminare questo pacchetto NPM perché i moduli \"{Modules}\" utilizzano questo pacchetto.", + "Volo.AbpIo.Domain:020003": "Impossibile eliminare questo pacchetto NPM perché i moduli \"{Modules}\" utilizzano questo pacchetto e i pacchetti Nuget \"{NugetPackages}\" dipendono da questo pacchetto.", + "Volo.AbpIo.Domain:020004": "Impossibile eliminare questo pacchetto Nuget perché i moduli \"{Modules}\" utilizzano questo pacchetto.", + "WantToLearn?": "Vuoi imparare?", + "ReadyToGetStarted?": "Pronto per iniziare?", + "JoinOurCommunity": "Unisciti alla nostra community", + "GetStartedUpper": "INIZIARE", + "ForkMeOnGitHub": "Fork me su GitHub", + "Features": "Caratteristiche", + "GetStarted": "Iniziare", + "Documents": "Documenti", + "Community": "Comunità", + "ContributionGuide": "Guida al contributo", + "Blog": "Blog", + "Commercial": "Commerciale", + "MyAccount": "Il mio conto", + "Permission:License": "Licenza", + "Permission:UserInfo": "Informazioni utente", + "SeeDocuments": "Vedi Documenti", + "Samples": "Campioni", + "Framework": "Struttura", + "Support": "Supporto" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json index 56f4ed934f..40b9fd3aa9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json @@ -34,6 +34,34 @@ "JoinOurMarketingNewsletter": "Join our marketing newsletter", "WouldLikeToReceiveMarketingMaterials": "I would like to receive marketing materials e.g. product deals & special offers.", "StartUsingYourLicenseNow": "Start using your license now!", - "WelcomePage": "Welcome Page" + "WelcomePage": "Welcome Page", + "CompanyName": "Company name", + "YourCompanyName": "Your company name", + "FirstName": "First name", + "LastName": "Last name", + "Optional": "Optional", + "YourFirstName": "Your first name", + "YourLastName": "Your last name", + "SpecialOffer": "Special Offer", + "SpecialOfferMessage": "Hurry up! Prices are valid for a limited time.", + "DiscountRequest": "Discount Request", + "DiscountRequestDescribeCustomerQuestion": "Which of the following describes you?", + "DiscountRequestStudentEmailMessage": "Email Address must contain 'edu'.", + "DiscountRequestDeveloperCount": "How many developers are you?", + "DiscountRequestDeveloperCountExceedMessage": "We don't provide discounted license for companies that has over {0} developers.", + "DiscountRequestOrganizationName": "Company/organization/school name", + "Website": "Website", + "GithubUsername": "GitHub username", + "PhoneNumber": "Phone number", + "Country": "Country", + "DescribeABPCommercialUsage": "Describe the project you are planning to develop based on APB Commercial", + "DiscountRequestCertifyInformationMessage": "I certify all information is true and correct.", + "DiscountRequestReceived": "We have received your discount request.", + "DiscountRequestStatusMessage": "We will respond to you after checking the information you have provided.", + "MVCOrRazorPages": "MVC (Razor Pages)", + "Angular": "Angular", + "Blazor": "Blazor", + "New": "New", + "MongoDB": "MongoDB" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 3c2a7cc59c..8259fb8160 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -291,6 +291,34 @@ "PayViaAmexCard": "How can I pay via my AMEX card?", "PayViaAmexCardDescription": "The default payment gateway 'Iyzico' may decline some AMEX credit cards due to the security measures. In this case, you can pay through the alternative payment gateway '2Checkout'.", "ThankYou": "Thank you", - "InvalidReCaptchaErrorMessage": "There was an error verifying reCAPTCHA. Please try again." + "InvalidReCaptchaErrorMessage": "There was an error verifying reCAPTCHA. Please try again.", + "CompanyName": "Company name", + "YourCompanyName": "Your company name", + "FirstName": "First name", + "LastName": "Last name", + "Optional": "Optional", + "YourFirstName": "Your first name", + "YourLastName": "Your last name", + "SpecialOffer": "Special Offer", + "SpecialOfferMessage": "Hurry up! Prices are valid for a limited time.", + "DiscountRequest": "Discount Request", + "DiscountRequestDescribeCustomerQuestion": "Which of the following describes you?", + "DiscountRequestStudentEmailMessage": "Email Address must contain 'edu'.", + "DiscountRequestDeveloperCount": "How many developers are you?", + "DiscountRequestDeveloperCountExceedMessage": "We don't provide discounted license for companies that has over {0} developers.", + "DiscountRequestOrganizationName": "Company/organization/school name", + "Website": "Website", + "GithubUsername": "GitHub username", + "PhoneNumber": "Phone number", + "Country": "Country", + "DescribeABPCommercialUsage": "Describe the project you are planning to develop based on APB Commercial", + "DiscountRequestCertifyInformationMessage": "I certify all information is true and correct.", + "DiscountRequestReceived": "We have received your discount request.", + "DiscountRequestStatusMessage": "We will respond to you after checking the information you have provided.", + "MVCOrRazorPages": "MVC (Razor Pages)", + "Angular": "Angular", + "Blazor": "Blazor", + "New": "New", + "MongoDB": "MongoDB" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json new file mode 100644 index 0000000000..b2da832b2a --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json @@ -0,0 +1,296 @@ +{ + "culture": "fi", + "texts": { + "OrganizationManagement": "Organisaation hallinta", + "OrganizationList": "Organisaatioluettelo", + "Volo.AbpIo.Commercial:010003": "Et ole tämän organisaation omistaja!", + "OrganizationNotFoundMessage": "Organisaatiota ei löytynyt!", + "DeveloperCount": "Kohdistetut / yhteensä kehittäjät", + "QuestionCount": "Jäljellä olevat / yhteensä kysymykset", + "Unlimited": "Rajoittamaton", + "Owners": "Omistajat", + "AddMember": "Lisää jäsen", + "AddOwner": "Lisää omistaja", + "AddDeveloper": "Lisää kehittäjä", + "UserName": "Käyttäjätunnus", + "Name": "Nimi", + "EmailAddress": "Sähköpostiosoite", + "Developers": "Kehittäjät", + "LicenseType": "Lisenssi-tyyppi", + "Manage": "Hallitse", + "StartDate": "Aloituspäivämäärä", + "EndDate": "Päättymispäivä", + "Modules": "Moduulit", + "LicenseExtendMessage": "Käyttöoikeutesi päättymispäivä on pidennetty {0}", + "LicenseUpgradeMessage": "Lisenssisi on päivitetty versioon {0}", + "LicenseAddDeveloperMessage": "{0} kehittäjää lisäsi lisenssiisi", + "Volo.AbpIo.Commercial:010004": "Määritettyä käyttäjää ei löydy! Käyttäjän on oltava jo rekisteröitynyt.", + "MyOrganizations": "Omat organisaatiot", + "ApiKey": "API-avain", + "UserNameNotFound": "Käyttäjää, jolla on käyttäjänimi {0}, ei ole", + "SuccessfullyAddedToNewsletter": "Kiitos, että tilasit uutiskirjeemme!", + "MyProfile": "Profiilini", + "EmailNotValid": "Ole hyvä ja syötä toimiva sähköpostiosoite.", + "JoinOurMarketingNewsletter": "Liity markkinointikirjeeseemme", + "WouldLikeToReceiveMarketingMaterials": "Haluaisin saada markkinointimateriaalia, kuten tuotetarjouksia ja erikoistarjouksia.", + "StartUsingYourLicenseNow": "Aloita lisenssin käyttö nyt!", + "WelcomePage": "Tervetuloa sivu", + "UnsubscriptionExpireEmail": "Peruuta lisenssin vanhentumispäivämäärän muistutussähköpostit", + "UnsubscribeLicenseExpireEmailReminderMessage": "Tämä sähköpostitilaus sisältää vain muistutuksen lisenssin vanhentumispäivästä.", + "UnsubscribeFromLicenseExpireEmails": "Jos et halua vastaanottaa lisenssin voimassaolon päättymispäivää koskevia sähköposteja, voit peruuttaa tilauksen milloin tahansa.", + "Unsubscribe": "Lopeta tilaus", + "NotOrganizationMember": "Et ole minkään organisaation jäsen.", + "UnsubscribeLicenseExpirationEmailSuccessTitle": "Tilauksen peruutus onnistui", + "UnsubscribeLicenseExpirationEmailSuccessMessage": "Et enää saa muistutuksia lisenssin vanhentumispäivästä.", + "IndexPageHeroSection": " Täydellinen verkkokehitysympäristö sisäänrakennettu kehys ", + "AbpCommercialShortDescription": "ABP Commercial tarjoaa valmiita sovellusmoduuleja, nopean sovelluskehitystyökalun, ammattimaiset käyttöliittymäteemat, ensiluokkaisen tuen ja paljon muuta.", + "LiveDemo": "Live-esittely", + "GetLicence": "Hanki lisenssi", + "Application": "Sovellus", + "StartupTemplates": "Käynnistysmallit", + "Startup": "Aloittaa", + "Templates": "Mallit", + "Developer": "Kehittäjä", + "Tools": "Työkalut", + "Premium": "Premium", + "PremiumSupport": "Ensiluokkainen tuki", + "PremiumForumSupport": "Premium-foorumin tuki", + "UI": "UI", + "Themes": "Teemat", + "JoinOurNewsletter": "Liity uutiskirjeemme", + "Send": "Lähettää", + "Learn": "Oppia", + "AdditionalServices": "Lisäpalvelut", + "WhatIsABPFramework": "MIKÄ ON ABP-KEHYS?", + "OpenSourceBaseFramework": "Avoimen lähdekoodin peruskehys", + "ABPFrameworkExplanation": "

ABP Commercial perustuu ABP Frameworkiin, avoimen lähdekoodin ja yhteisövetoiseen verkkosovelluskehykseen ASP.NET Core -sovellukselle.

ABP Framework tarjoaa erinomaisen infrastruktuurin ylläpitettävien, laajennettavien tiedostojen kirjoittamiseen. ja testattava koodi parhailla käytänteillä.

Rakennettu ja integroitu jo tunnettujen suosittujen työkalujen kanssa. Matala oppimiskäyrä, helppo sopeutuminen, mukava kehitys.

", + "Modular": "Modulaarinen", + "MicroserviceCompatible": "Mikropalvelu yhteensopiva", + "DomainDrivenDesignInfrastructure": "Toimialueohjattu suunnittelun infrastruktuuri", + "MultiTenancy": "Monivuokraus", + "DistributedMessaging": "Hajautetut viestit", + "DynamicProxying": "Dynaaminen välityspalvelin", + "BackgroundJobs": "Taustatyöt", + "AuditLogging": "Tarkastusten kirjaaminen", + "BLOBStoring": "BLOB-tallennus", + "BundlingMinification": "Niputtaminen ja minimointi", + "AdvancedLocalization": "Edistynyt lokalisointi", + "ManyMore": "Monta lisää", + "ExploreTheABPFramework": "Tutustu ABP-kehykseen", + "WhyUseTheABPCommercial": "Miksi käyttää ABP-mainosta?", + "WhyUseTheABPCommercialExplanation": "

Yritysluokan verkkosovellusten rakentaminen voi olla monimutkaista ja aikaa vievää.

ABP Commercial tarjoaa täydellisen perusinfrastruktuurin, joka tarvitaan kaikille nykyaikaisille yritystason ASP.NET-ytimille perustuvat ratkaisut. ABP: n sisäänrakennetut ominaisuudet ja moduulit tukevat koko suunnittelusykliä suunnittelusta käyttöönottoon asti.

", + "StartupTemplatesShortDescription": "Käynnistysmallien avulla voit aloittaa projektisi muutamassa sekunnissa.", + "UIFrameworksOptions": "Käyttöliittymäkehysvaihtoehdot;", + "DatabaseProviderOptions": "Tietokannan tarjoajan vaihtoehdot;", + "PreBuiltApplicationModules": "Valmiit sovellusmoduulit", + "PreBuiltApplicationModulesShortDescription": "Yleisimmät sovellusvaatimukset on jo kehitetty sinulle uudelleenkäytettävinä moduuleina.", + "Account": "Tili", + "Blogging": "Bloggaaminen", + "Identity": "Identiteetti", + "IdentityServer": "Identity Server", + "Saas": "Saas", + "LanguageManagement": "Kielen hallinta", + "TextTemplateManagement": "Tekstimallien hallinta", + "See All Modules": "Katso kaikki moduulit", + "ABPSuite": "ABP Suite", + "AbpSuiteShortDescription": "ABP Suite on ABP-mainosmateriaalia täydentävä työkalu.", + "AbpSuiteExplanation": "Sen avulla voit rakentaa verkkosivuja muutamassa minuutissa. Se on .NET Core Global -työkalu, joka voidaan asentaa komentoriviltä. Se voi luoda uuden ABP-ratkaisun, luoda CRUD-sivuja tietokannasta käyttöliittymään.", + "Details": "Yksityiskohdat", + "LeptonTheme": "Lepton-teema", + "ProfessionalModernUIThemes": "Ammattimaiset, modernit käyttöliittymäteemat", + "LeptonThemeExplanation": "Lepton tarjoaa valikoiman Bootstrap-järjestelmänvalvojan teemoja, jotka ovat vankka perusta mille tahansa projektille, joka vaatii järjestelmänvalvojan hallintapaneelin.", + "DefaultTheme": "Oletusteema", + "MaterialTheme": "Materiaaliteema", + "Default2Theme": "Oletus 2 teema", + "DarkTheme": "Tumma teema", + "DarkBlueTheme": "Tummansininen teema", + "LightTheme": "Kevyt teema", + "ProudToWorkWith": "Ylpeä työskennellä", + "OurConsumers": "Sadat yritykset ja kehittäjät yli 50 maassa ympäri maailmaa luottavat ABP Commercialiin.", + "JoinOurConsumers": "Liity heihin ja rakenna upeita tuotteita nopeasti.", + "AdditionalServicesExplanation": "Tarvitsetko lisä- tai mukautettuja palveluita? Me ja kumppanimme voimme tarjota; ", + "CustomProjectDevelopment": "Mukautettu projektikehitys", + "CustomProjectDevelopmentExplanation": "Omistetut kehittäjät mukautetuille projekteillesi.", + "PortingExistingProjects": "Olemassa olevien projektien siirtäminen", + "PortingExistingProjectsExplanation": "Vanhojen projektien siirtäminen ABP-alustalle.", + "LiveSupport": "Live-tuki", + "LiveSupportExplanation": "Live-etätukivaihtoehto, kun tarvitset sitä.", + "Training": "Koulutus", + "TrainingExplanation": "Oma koulutus kehittäjille.", + "OnBoarding": "Perehdytys", + "OnBoardingExplanation": "Auta määrittämään kehitys-, CI- ja CD-ympäristösi.", + "PrioritizedTechnicalSupport": "Ensisijainen tekninen tuki", + "PremiumSupportExplanation": "ABP-kehyksen suuren yhteisötuen lisäksi tukitiimimme vastaa ensisijaisesti kaupallisten käyttäjien teknisiin kysymyksiin ja ongelmiin.", + "SeeTheSupportOptions": "Katso tukivaihtoehdot", + "Contact": "Ottaa yhteyttä", + "TellUsWhatYouNeed": "Kerro meille mitä tarvitset.", + "YourMessage": "Viestisi", + "YourFullName": "Koko nimesi", + "EmailField": "Sähköpostiosoite", + "YourEmailAddress": "Sähköpostiosoitteesi", + "HowMayWeHelpYou": "Kuinka voimme auttaa sinua?", + "SendMessage": "Lähetä viesti", + "Success": "Menestys", + "WeWillReplyYou": "Saimme viestisi ja otamme sinuun pian yhteyttä.", + "GoHome": "Mene kotiin", + "CreateLiveDemo": "Luo live-esittely", + "RegisterToTheNewsletter": "Rekisteröidy uutiskirjeeseen saadaksesi tietoa ABP.IO: sta, mukaan lukien uudet julkaisut jne.", + "EnterYourEmailOrLogin": "Kirjoita sähköpostiosoitteesi luodaksesi esittely tai kirjaudu sisään nykyisellä tililläsi.", + "ApplicationTemplate": "Sovelluksen malli", + "ApplicationTemplateExplanation": "Sovelluksen käynnistysmallia käytetään uuden verkkosovelluksen luomiseen.", + "EfCoreProvider": "Entity Framework (tukee SQL Serveriä, MySQL: ää, PostgreSQL: ää, Oracle ja muita )", + "AlreadyIncludedInTemplateModules": "Seuraavat moduulit ovat jo mukana ja määritetty tähän malliin:", + "ApplicationTemplateArchitecture": "Tämä sovellusmalli tukee myös porrastettua arkkitehtuuria, jossa käyttöliittymäkerros, API-kerros ja todennuspalvelu on fyysisesti erotettu.", + "SeeTheGuideOrGoToTheLiveDemo": "Katso teknistä tietoa tästä mallista kehittäjän oppaasta tai siirry live-esittelyyn.", + "DeveloperGuide": "Kehittäjän opas", + "ModuleTemplate": "Moduulimalli", + "ModuleTemplateExplanation1": "Haluatko luoda moduulin ja käyttää sitä uudelleen eri sovelluksissa? Tämä käynnistysmalli valmistaa kaiken aloittamaan uudelleenkäytettävän sovellusmoduulin tai mikropalvelun luomisen.", + "ModuleTemplateExplanation2": "

Voit tukea yhtä tai useampaa käyttöliittymäkehystä, yhtä tai useampaa tietokantapalvelua yhdelle moduulille. Käynnistysmalli on määritetty suorittamaan ja testaamaan moduulia pienimmässä sovelluksessa yksikön ja integraatiotestiinfrastruktuurin lisäksi.

Katso teknistä tietoa mallista kehittäjän oppaasta.

", + "WithAllStyleOptions": "kaikilla tyylivaihtoehdoilla", + "Demo": "Demo", + "SeeAllModules": "Katso kaikki moduulit", + "ABPCLIExplanation": "ABP CLI (Command Line Interface) on komentorivityökalu joidenkin yleisten toimintojen suorittamiseen ABP-pohjaisiin ratkaisuihin.", + "ABPSuiteEasilyCURD": "ABP Suite on työkalu, jonka avulla voit helposti luoda CRUD-sivuja", + "WeAreHereToHelp": " Apua olemme täällä", + "BrowseOrAskQuestion": "Voit selata ohjeaiheitamme tai etsiä usein kysyttyjä kysymyksiä tai voit esittää meille kysymyksiä yhteydenottolomakkeella .", + "SearchQuestionPlaceholder": "Hae usein kysyttyjä kysymyksiä", + "WhatIsTheABPCommercial": "Mikä on ABP-kauppa?", + "WhatAreDifferencesThanAbpFramework": "Mitä eroja on avoimen lähdekoodin ABP Frameworkilla ja ABP Commercialilla?", + "ABPCommercialExplanation": "ABP Commercial on joukko ensiluokkaisia moduuleja, työkaluja, teemoja ja palveluja, jotka on rakennettu avoimen lähdekoodin ABP-kehyksen päälle. ABP Commercial kehittää ja tukee samaa tiimiä ABP-kehyksen takana.", + "WhatAreDifferencesThanABPFrameworkExplanation": "

ABP-kehys on modulaarinen, teemoitettava, mikropalvelujen kanssa yhteensopiva sovelluskehys ASP.NET Core -sovellukselle. Se tarjoaa täydellisen arkkitehtuurin ja vahvan infrastruktuurin, joka saa sinut keskittymään omaan yrityskoodiin sen sijaan, että toistat itsesi jokaisessa uudessa projektissa. Se perustuu ohjelmistokehityksen parhaisiin käytäntöihin ja jo tiedettyihin suosittuihin työkaluihin.

ABP-kehykset ovat täysin ilmaisia, avoimen lähdekoodin ja yhteisölähtöisiä. Se tarjoaa myös ilmaisen teeman ja joitain valmiita moduuleja (esim. Henkilöllisyyden hallinta ja vuokralaisten hallinta).

", + "VisitTheFrameworkVSCommercialDocument": "Vieraile seuraavalla linkillä saadaksesi lisätietoja {1} ", + "ABPCommercialFollowingBenefits": "ABP Commercial lisää seuraavat edut ABP-kehyksen päälle;", + "Professional": "Ammattilainen", + "UIThemes": "Käyttöliittymän teemat", + "EnterpriseModules": "Yrityskäyttöiset, monipuoliset, valmiit sovellusmoduulit (esim. Identity Server -hallinta, SaaS-hallinta, kielen hallinta)", + "ToolingToSupport": "Työkalut, jotka tukevat kehitystesi tuottavuutta (esim. ABP Suite )", + "PremiumSupportLink": "Ensiluokkainen tuki ", + "WhatDoIDownloadABPCommercial": "Mitä lataan ostaessani ABP Commercial -palvelua?", + "CreateUnlimitedSolutions": "Kun olet ostanut ABP Commercial -lisenssin, voit luoda rajoittamattomia ratkaisuja, kuten Aloittaminen -asiakirjassa kuvataan.", + "ABPCommercialSolutionExplanation": "Kun luot uuden sovelluksen, saat Visual Studio -ratkaisun (käynnistysmalli) mieltymystesi perusteella. Ladatussa ratkaisussa on kaupallisia moduuleja ja teemoja, jotka on jo asennettu ja määritetty sinulle. Voit poistaa esiasennetun moduulin tai lisätä toisen moduulin, jos haluat. Kaikissa moduuleissa ja teemoissa käytetään oletuksena NuGet / NPM-paketteja.", + "StartDevelopWithTutorials": "Ladattu ratkaisu on hyvin suunniteltu ja dokumentoitu. Voit aloittaa oman yrityskoodisi kehittämisen sen perusteella opetusohjelmien mukaisesti", + "TryTheCommercialDemo": "Voit kokeilla esittelyä nähdäksesi esimerkkisovelluksen, joka on luotu ABP Commercial -käynnistysmallin avulla.", + "HowManyProducts": "Kuinka monta erilaista tuotetta / ratkaisua voin rakentaa ABP Commercial -sovelluksella?", + "HowManyProductsExplanation": "ABP-projektin luomiselle ei ole rajoituksia. Voit luoda niin monta projektia kuin haluat, kehittää ja ladata ne eri palvelimille.", + "HowManyDevelopers": "Kuinka monta kehittäjää voi työskennellä ABP-kaupassa?", + "HowManyDevelopersExplanation": "ABP Commercial -lisenssit ovat kehittäjää kohti. Eri lisenssityypeillä on erilaiset kehittäjien rajoitukset. Voit kuitenkin lisätä lisää kehittäjiä mihin tahansa lisenssityyppiin milloin tahansa. Katso hinnat -sivulta lisenssityypit, kehittäjien rajoitukset ja kehittäjien lisäkustannukset.", + "ChangingLicenseType": "Voinko muuttaa lisenssityyppiäni tulevaisuudessa?", + "ChangingLicenseTypeExplanation": "Voit aina lisätä uusia kehittäjiä samaan lisenssityyppiin. Katso myös \"Kuinka monta kehittäjää voi työskennellä ABP Commercialilla?\". Voit myös päivittää korkeampaan lisenssiin maksamalla lasketun hintaeron. Kun päivität korkeampaan lisenssisuunnitelmaan, saat uuden suunnitelman edut, mutta lisenssin päivitys ei muuta lisenssin voimassaolon päättymispäivää.", + "LicenseExtendUpgradeDiff": "Mitä eroa on lisenssin laajennuksella ja päivityksellä?", + "LicenseExtendUpgradeDiffExplanation": " Laajentaminen: Laajentamalla / uusimalla käyttöoikeutta saat jatkossakin ensiluokkaista tukea ja saat tärkeitä päivityksiä moduuleille ja teemoille. Lisäksi voit jatkaa uusien projektien luomista. Ja voit silti käyttää ABP Suitea, joka vauhdittaa kehitystäsi.
Päivittäminen: Päivittämällä lisenssisi edistyt korkeampaan lisenssisuunnitelmaan, jonka avulla voit saada lisäetuja . Katso lisenssisuunnitelmien väliset erot lisenssien vertailutaulukosta . Toisaalta, kun päivität, lisenssin vanhentumispäivä ei muutu! Lisenssin päättymispäivän jatkamiseksi sinun on jatkettava käyttöoikeutta.", + "LicenseRenewalCost": "Mitkä ovat lisenssin uusimiskustannukset vuoden kuluttua?", + "LicenseRenewalCostExplanation": "Kaikkien ABP Commercial perpetual -lisenssien uusimis- (laajennus) hinta on {0} lisenssiluettelohinnasta. Tavallisen tiimilisenssin uusimishinta on $ {1}, tavallinen yrityslisenssi on $ {2} ja tavallinen yrityslisenssi on $ {3}. Jos olet jo asiakas, kirjaudu tilillesi ja tarkista käytettävissä oleva uusimishinta.", + "HowDoIRenewMyLicense": "Kuinka uusin lisenssin?", + "HowDoIRenewMyLicenseExplanation": "Voit uusia käyttöoikeutesi siirtymällä organisaation hallintasivulle . Jotta voisit hyödyntää alennettujen varhaisen uusimisen hintojamme, muista uusia ennen lisenssin voimassaolon päättymistä. Älä huoli siitä, ettet tiedä, milloin Varhaisen uudistamisen mahdollisuus sulkeutuu. Saat kaksi muistutussähköpostia ennen tilauksesi päättymistä. Lähetämme ne 30 päivää, 7 päivää ennen vanhenemista.", + "IsSourceCodeIncluded": "Sisältääkö lisenssini kaupallisten moduulien ja teemojen lähdekoodin?", + "IsSourceCodeIncludedExplanation1": "Riippuu ostamastasi lisenssityypistä:", + "IsSourceCodeIncludedExplanation2": " Tiimi : Ratkaisusi käyttää moduuleja ja teemoja NuGet- ja NPM-paketteina. Se ei sisällä heidän lähdekoodiaan. Tällä tavoin voit helposti päivittää nämä moduulit ja teemat aina, kun uusi versio on saatavana. Et kuitenkaan voi saada moduulien ja teemojen lähdekoodia.", + "IsSourceCodeIncludedExplanation3": " Yritys / yritys : Tiimilisenssin lisäksi voit ladata minkä tahansa tarvitsemasi moduulin tai teeman lähdekoodin. Voit jopa poistaa tietyn moduulin NuGet / NPM-pakettiviitteet ja lisätä sen lähdekoodin suoraan ratkaisuusi sen muuttamiseksi kokonaan.", + "IsSourceCodeIncludedExplanation4": "

Moduulin lähdekoodin sisällyttäminen ratkaisuun antaa sinulle maksimaalisen vapauden mukauttaa moduulia. Tällöin moduulia ei voida päivittää automaattisesti, kun uusi versio julkaistaan.

Mikään lisensseistä ei sisällä ABP Suiten lähdekoodia, joka on ulkoinen työkalu, joka tuottaa koodia sinulle ja auttaa kehitykseen.

Katso muita lisenssityyppien eroja hinnoittelusivulta .

", + "ChangingDevelopers": "Voinko muuttaa organisaationi rekisteröityneitä kehittäjiä tulevaisuudessa?", + "ChangingDevelopersExplanation": "Uusien kehittäjien lisäämisen lisenssiin lisäksi voit myös muuttaa olemassa olevia kehittäjiä (voit poistaa kehittäjän ja lisätä uuden samalle paikalle) ilman lisäkustannuksia.", + "WhatHappensWhenLicenseEnds": "Mitä tapahtuu, kun lisenssikauteni päättyy?", + "WhatHappensWhenLicenseEndsExplanation1": "ABP Commercial -lisenssityyppi on jatkuva lisenssi . Kun lisenssi vanhenee, voit jatkaa projektisi kehittämistä. Ja sinun ei tarvitse uudistaa lisenssiäsi. Lisenssisi mukana toimitetaan yhden vuoden päivitys- ja tukisuunnitelma. Jos haluat edelleen saada uusia ominaisuuksia, suorituskyvyn parannuksia, virhekorjauksia, tukea ja jatkaa ABP Suite -sovelluksen käyttöä, muista uusia suunnitelma joka vuosi. Kun lisenssi vanhenee, et voi saada enemmän seuraavista eduista;", + "WhatHappensWhenLicenseEndsExplanation2": "Et voi luoda uusia ratkaisuja ABP Commercial -sovelluksella, mutta voit jatkaa olemassa olevien sovellusten kehittämistä ikuisesti.", + "WhatHappensWhenLicenseEndsExplanation3": "Voit saada päivityksiä moduuleista ja teemoista MAJOR-versiostasi. Esimerkiksi; jos käytät moduulin v3.2.0-versiota, voit silti saada päivityksiä kyseisen moduulin versiolle v3.x.x (v3.3.0, v3.5.2 ... jne.). Mutta et voi saada päivityksiä seuraavaan pääversioon (kuten v4.x, v5.x)", + "WhatHappensWhenLicenseEndsExplanation4": "Et voi asentaa uusia moduuleja ja teemoja, jotka on lisätty ABP Commercial -alustalle käyttöoikeuden päättymisen jälkeen.", + "WhatHappensWhenLicenseEndsExplanation5": "Et voi käyttää ABP Suitea.", + "WhatHappensWhenLicenseEndsExplanation6": "Et voi enää saada premium-tukea .", + "WhatHappensWhenLicenseEndsExplanation7": "Voit uusia tilauksesi, jos haluat jatkaa näiden etujen saamista. Tilauksen uusimisessa on 20% alennus.", + "WhenShouldIRenewMyLicense": "Milloin minun pitäisi uusia lisenssini?", + "WhenShouldIRenewMyLicenseExplanation1": "Jos uusit lisenssin kuukauden kuluessa lisenssin voimassaolon päättymisestä, lisenssin kokonaishintaan sovelletaan 20% alennusta.", + "WhenShouldIRenewMyLicenseExplanation2": "Jos uusit lisenssin kuukauden kuluttua lisenssin voimassaolon päättymispäivästä, uusimishinta on sama kuin lisenssin ostohinta eikä uusimiselle ole alennusta.", + "TrialPlan": "Onko sinulla kokeilusuunnitelma?", + "TrialPlanExplanation": "Toistaiseksi ABP Commercialilla ei ole kokeilusuunnitelmaa. Joukkueen lisensseille tarjoamme 30 päivän rahanpalautustakuun. Voit vain pyytää hyvitystä 30 ensimmäisen päivän aikana. Yritys- ja yrityslisensseille hyvitämme 60% 30 päivässä. Tämä johtuu siitä, että yritys- ja yrityslisenssit sisältävät kaikkien moduulien ja teemojen täydellisen lähdekoodin.", + "DoYouAcceptBankWireTransfer": "Hyväksytkö pankkisiirron?", + "DoYouAcceptBankWireTransferExplanation": "Kyllä, hyväksymme pankkisiirron.
Kun olet lähettänyt lisenssimäärän pankkisiirrolla, lähetä meille kuitti ja pyydetty lisenssityyppi sähköpostitse.
Kansainväliset pankkitilitiedot:", + "HowToUpgrade": "Kuinka päivittää olemassa olevia sovelluksia, kun uusi versio on saatavilla?", + "HowToUpgradeExplanation1": "Kun luot uuden sovelluksen ABP Commercial -sovelluksella, kaikkia moduuleja ja teemaa käytetään NuGet- ja NPM-paketteina. Joten voit päivittää paketit helposti, kun uusi versio on saatavilla.", + "HowToUpgradeExplanation2": "Normaalien NuGet / NPM-päivitysten lisäksi ABP CLI tarjoaa päivityskomennon, joka etsii ja päivittää kaikki ratkaisusi ABP-paketit.", + "DatabaseSupport": "Mitä tietokantajärjestelmiä tuetaan?", + "DatabaseSupportExplanation": "ABP Framework itsessään on tietokanta-agnostinen ja voi luonteeltaan työskennellä minkä tahansa tietokantapalvelujen kanssa. Katso tietojen käyttöasiakirjasta luettelo tällä hetkellä toteutetuista palveluntarjoajista.", + "UISupport": "Mitä käyttöliittymäkehyksiä tuetaan?", + "Supported": "Tuettu", + "UISupportExplanation": "ABP Framework itsessään on käyttöliittymäkehyksen agnostikko ja voi toimia minkä tahansa käyttöliittymäkehyksen kanssa. Käynnistysmalleja, moduulin käyttöliittymiä ja teemoja ei kuitenkaan otettu käyttöön kaikissa käyttöliittymäkehyksissä. Katso käyttöliittymävaihtoehtojen ajantasainen luettelo aloitusasiakirjasta .", + "MicroserviceSupport": "Tukeeko se mikropalveluarkkitehtuuria?", + "MicroserviceSupportExplanation1": "Yksi sivutuotekehyksen tärkeimmistä tavoitteista on tarjota kätevä infrastruktuuri mikropalveluratkaisujen luomiseksi. Katso mikropalveluarkkitehtuuri -asiakirjasta, miten se auttaa luomaan mikropalvelujärjestelmiä.", + "MicroserviceSupportExplanation2": "Kaikki ABP Commercial -moduulit on suunniteltu tukemaan mikropalvelujen käyttöönottotilanteita (omalla sovellusliittymällä ja tietokannalla) noudattamalla moduulien kehittämisen parhaita käytäntöjä -asiakirjaa.", + "MicroserviceSupportExplanation3": "Tarjoamme esimerkin mikropalveluiden esittelyratkaisusta , joka osoittaa mikropalveluarkkitehtuurin toteutuksen auttaakseen sinua luomaan oman ratkaisun.", + "MicroserviceSupportExplanation4": "Lyhyt vastaus on \" kyllä, se tukee mikropalveluarkkitehtuuria \".", + "MicroserviceSupportExplanation5": "Mikropalvelujärjestelmä on kuitenkin ratkaisu, ja jokaisella ratkaisulla on erilaiset vaatimukset, verkon topologia, viestintätavat, todennusmahdollisuudet, tietokannan erottamis- / jakamispäätökset, ajonaikaiset kokoonpanot, kolmannen osapuolen järjestelmäintegraatiot ja paljon muuta.", + "MicroserviceSupportExplanation6": "ABP Framework ja ABP Commercial tarjoavat infrastruktuurin mikropalvelumalleja varten, mikropalvelujen kanssa yhteensopivia moduuleja, näytteitä ja dokumentaatiota, jotka auttavat sinua rakentamaan oman ratkaisun. Mutta älä odota lataavan unelmaratkaisua suoraan sinulle valmiiksi. Sinun täytyy ymmärtää se ja tuoda joitain osia toiveidesi mukaan.", + "WhereCanIDownloadSourceCode": "Mistä voin ladata lähdekoodin?", + "WhereCanIDownloadSourceCodeExplanation": "Voit ladata kaikkien ABP-moduulien, kulmapakettien ja teemojen lähdekoodin ABP Suite- tai ABP CLI -palvelun kautta. Katso Lähdekoodin lataaminen? ", + "ComputerLimitation": "Kuinka monta tietokonetta kehittäjä voi kirjautua kehittäessään ABP: tä?", + "ComputerLimitationExplanation": "Sallimme erikseen {0} tietokoneet yksittäistä / lisensoitua kehittäjää kohti. Aina kun kehittäjän on tarpeen kehittää ABP Commercial -tuotteita kolmannella koneella, on lähetettävä sähköpostiviesti osoitteeseen license@abp.io, jossa selitetään tilanne, ja sitten suoritamme sopivan varauksen järjestelmäämme.", + "RefundPolicy": "Onko sinulla hyvityskäytäntö?", + "RefundPolicyExplanation": "Voit pyytää hyvitystä 30 päivän kuluessa lisenssiostoksestasi. Yritys- ja yrityslisenssityypeillä on lähdekoodin latausvaihtoehto, joten hyvityksiä ei ole saatavana yrityksille ja yrityksille (eikä lisensseille, jotka sisältävät oikeuden saada lähdekoodia). Lisäksi uusimista ja toisen lisenssin ostoja ei hyvitetä.", + "HowCanIRefundVat": "Kuinka voin palauttaa arvonlisäveron?", + "HowCanIRefundVatExplanation1": "Jos suoritit maksun käyttämällä 2Checkoutia, voit palauttaa arvonlisäveron 2Checkout-tilisi kautta:", + "HowCanIRefundVatExplanation2": "Kirjaudu sisään 2Tarkista -tiliisi.", + "HowCanIRefundVatExplanation3": "Etsi sopiva tilaus ja paina \"Hyvitä myöhässä oleva alv\" (kirjoita ALV-tunnuksesi)", + "HowCanIGetMyInvoice": "Kuinka saan laskuni?", + "HowCanIGetMyInvoiceExplanation": "Lisenssin ostamiseen on 2 maksuyhdyskäytävää: PayU ja 2Checkout. Jos ostat lisenssin 2Checkout gatewayn kautta, se lähettää PDF-laskun sähköpostiosoitteeseesi, katso 2Tarkista laskutus. Jos ostat PayU-yhdyskäytävän kautta tai pankkisiirrolla, valmistelemme ja lähetämme laskusi. Voit pyytää laskua organisaation hallintasivulta ", + "Forum": "Foorumi", + "SupportExplanation": "ABP Commercial -lisenssit tarjoavat ensiluokkaisen foorumituen ABP-kehyksen asiantuntijoista koostuvalle tiimille.", + "PrivateTicket": "Yksityinen lippu", + "PrivateTicketExplanation": "Yrityslisenssi sisältää myös yksityisen tuen sähköposti- ja lippujärjestelmällä.", + "AbpSuiteExplanation1": "ABP Suiten avulla voit luoda verkkosivuja muutamassa minuutissa. Se on .NET Core Global -työkalu, joka voidaan asentaa komentoriviltä.", + "AbpSuiteExplanation2": "Se voi luoda uuden ABP-ratkaisun, luoda CRUD-sivuja tietokannasta käyttöliittymään. Katso tekninen yleiskatsaus asiakirjasta ", + "FastEasy": "Nopea ja helppo", + "AbpSuiteExplanation3": "ABP Suiten avulla voit luoda helposti CRUD-sivuja. Sinun tarvitsee vain määritellä entiteetti ja sen ominaisuudet, antaa loput ABP Suiten puolestasi! ABP Suite luo kaikki tarvittavat koodit CRUD-sivullesi muutamassa sekunnissa. Se tukee Angular-, MVC- ja Blazor-käyttöliittymiä.", + "RichOptions": "Monipuoliset vaihtoehdot", + "AbpSuiteExplanation4": "ABP Suite tukee useita käyttöliittymävaihtoehtoja, kuten Razor Pages ja Kulma .Se tukee myös useita tietokantoja, kuten MongoDB ja kaikkia EntityFramework Core <: n tukemia tietokantoja. / strong> (MS SQL Server, Oracle, MySql, PostgreSQL ja lisää ).", + "AbpSuiteExplanation5": "Hyvä asia on, että sinun ei tarvitse huolehtia näistä vaihtoehdoista. ABP Suite ymmärtää projektisi tyypin ja luo koodin projektillesi ja sijoittaa luodun koodin oikeaan paikkaan projektissasi.", + "SourceCode": "Lähdekoodi", + "AbpSuiteExplanation6": "ABP Suite luo lähdekoodin sinulle! Se ei luo taikuustiedostoja verkkosivun luomiseksi. ABP Suite luo lähdekoodin Entity, Repository, Application Service, Code First Migration, JavaScript / TypeScript ja CSHTML / HTML sekä tarvittavat liitännät. ABP Suite tuottaa koodin myös ohjelmistokehityksen parhaiden käytäntöjen mukaisesti, joten sinun ei tarvitse huolehtia luodun koodin laadusta.", + "AbpSuiteExplanation7": "Koska luotun CRUD-sivun rakennuspalikoiden lähdekoodi on oikeissa sovelluskerroksissa, voit helposti muokata lähdekoodia ja pistää mukautetun / bussiness-logiikan luotuun koodiin.", + "CrossPlatform": "Cross Platform", + "AbpSuiteExplanation8": "ABP Suite on rakennettu .NET Core -sovelluksella ja se on alustojen välinen. Se toimii verkkosovelluksena paikallisella tietokoneellasi. Voit käyttää sitä Windows , Mac ja Linux ", + "OtherFeatures": "Muut ominaisuudet", + "OtherFeatures1": "Päivittää ratkaisusi NuGet ja NPM -paketit helposti.", + "OtherFeatures2": "Palauttaa jo luodut sivut tyhjästä.", + "OtherFeatures3": "Luo uusia ratkaisuja", + "ThanksForCreatingProject": "Kiitos projektin luomisesta!", + "HotToRunSolution": "Kuinka ajaa ratkaisusi?", + "HotToRunSolutionExplanation": "Katso aloitusasiakirjasta lisätietoja ratkaisun määrittämisestä ja ajamisesta.", + "GettingStarted": "Päästä alkuun", + "WebAppDevTutorial": "Verkkosovellusten kehittäjän opetusohjelma", + "WebAppDevTutorialExplanation": "Katso vaiheittainen kehitysnäyte verkkosovellusten kehittämisoppaasta.", + "Document": "Asiakirja", + "UsingABPSuiteToCURD": "ABP Suiten käyttäminen CRUD-sivunluontia ja työkaluja varten", + "SeeABPSuiteDocument": "Katso ABP Suite -asiakirjasta ABP Suiten käyttö.", + "AskQuestionsOnSupport": "Voit esittää kysymyksiä ABP: n kaupallisesta tuesta.", + "Documentation": "Dokumentointi", + "SeeModulesDocument": "Katso moduulidokumentista luettelo kaikista kaupallisista (pro) moduuleista ja niiden asiakirjoista.", + "Pricing": "Hinnoittelu", + "PricingExplanation": "Valitse ominaisuudet ja toiminnot, joita yrityksesi tarvitsee tänään. Päivitä helposti, kun yrityksesi kasvaa.", + "Team": "Tiimi", + "Business": "Liiketoiminta", + "Enterprise": "Yritys", + "Custom": "Mukautettu", + "IncludedDeveloperLicenses": "Mukana kehittäjälisenssit", + "CustomLicenceOrAdditionalServices": "Tarvitsetko mukautettua lisenssiä tai lisäpalveluja?", + "CustomOrVolumeLicense": "Mukautettu tai volyymilisenssi", + "LiveTrainingSupport": "Live-koulutus ja tuki", + "AndMore": "ja enemmän", + "AdditionalDeveloperLicense": "Kehittäjän lisenssi", + "ProjectCount": "Projektilaskenta", + "AllProModules": "Kaikki pro-moduulit", + "AllProThemes": "Kaikki pro-teemat", + "AllProStartupTemplates": "Kaikki pro-käynnistysmallit", + "SourceCodeOfAllModules": "Kaikkien moduulien lähdekoodi", + "SourceCodeOfAllThemes": "Kaikkien teemojen lähdekoodi", + "PerpetualLicense": "Jatkuva lisenssi", + "UnlimitedServerDeployment": "Rajoittamaton palvelimen käyttöönotto", + "YearUpgrade": "1 vuoden päivitys", + "YearPremiumForumSupport": "Yhden vuoden premium-foorumin tuki", + "ForumSupportIncidentCountYear": "Foorumin tuen tapahtumien määrä / vuosi", + "PrivateTicketEmailSupport": "Yksityinen lippu- ja sähköpostituki", + "BuyNow": "Osta nyt", + "PayViaAmexCard": "Kuinka voin maksaa AMEX-korttini kautta?", + "PayViaAmexCardDescription": "Oletusmaksuyhdyskäytävä 'Iyzico' voi hylätä tietyt AMEX-luottokortit turvatoimenpiteiden takia. Tässä tapauksessa voit maksaa vaihtoehtoisen maksuyhdyskäytävän '2Checkout' kautta.", + "ThankYou": "Kiitos", + "InvalidReCaptchaErrorMessage": "ReCAPTCHA: n vahvistamisessa tapahtui virhe. Yritä uudelleen." + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json new file mode 100644 index 0000000000..c5f9f1db6c --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json @@ -0,0 +1,296 @@ +{ + "culture": "fr", + "texts": { + "OrganizationManagement": "Gestion de l'organisation", + "OrganizationList": "Liste des organisations", + "Volo.AbpIo.Commercial:010003": "Vous n'êtes pas propriétaire de cette organisation!", + "OrganizationNotFoundMessage": "Aucune organisation trouvée!", + "DeveloperCount": "Développeurs alloués / totaux", + "QuestionCount": "Questions restantes / totales", + "Unlimited": "Illimité", + "Owners": "Propriétaires", + "AddMember": "Ajouter un membre", + "AddOwner": "Ajouter un propriétaire", + "AddDeveloper": "Ajouter un développeur", + "UserName": "Nom d'utilisateur", + "Name": "Nom", + "EmailAddress": "Adresse e-mail", + "Developers": "Développeurs", + "LicenseType": "Type de licence", + "Manage": "Gérer", + "StartDate": "Date de début", + "EndDate": "Date de fin", + "Modules": "Modules", + "LicenseExtendMessage": "La date de fin de votre licence est étendue au {0}", + "LicenseUpgradeMessage": "Votre licence est mise à niveau vers {0}", + "LicenseAddDeveloperMessage": "{0} développeurs ajoutés à votre licence", + "Volo.AbpIo.Commercial:010004": "Impossible de trouver l'utilisateur spécifié! L'utilisateur doit être déjà enregistré.", + "MyOrganizations": "Mes organisations", + "ApiKey": "Clé API", + "UserNameNotFound": "Il n'y a aucun utilisateur avec le nom d'utilisateur {0}", + "SuccessfullyAddedToNewsletter": "Merci de vous être abonné à notre newsletter!", + "MyProfile": "Mon profil", + "EmailNotValid": "S'il vous plaît, mettez une adresse email valide.", + "JoinOurMarketingNewsletter": "Rejoignez notre newsletter marketing", + "WouldLikeToReceiveMarketingMaterials": "Je souhaite recevoir des supports marketing tels que des offres de produits et des offres spéciales.", + "StartUsingYourLicenseNow": "Commencez à utiliser votre licence maintenant!", + "WelcomePage": "Page d'accueil", + "UnsubscriptionExpireEmail": "Se désabonner des e-mails de rappel de la date d'expiration de la licence", + "UnsubscribeLicenseExpireEmailReminderMessage": "Cet abonnement par e-mail ne contient que le rappel de la date d'expiration de votre licence.", + "UnsubscribeFromLicenseExpireEmails": "Si vous ne souhaitez pas recevoir les e-mails concernant la date d'expiration de votre licence, vous pouvez vous désinscrire à tout moment.", + "Unsubscribe": "Se désabonner", + "NotOrganizationMember": "Vous n'êtes membre d'aucune organisation.", + "UnsubscribeLicenseExpirationEmailSuccessTitle": "Désabonnement réussi", + "UnsubscribeLicenseExpirationEmailSuccessMessage": "Vous ne recevrez plus d'e-mails de rappel de la date d'expiration de la licence.", + "IndexPageHeroSection": "Une plate-forme de développement Web complète intégrée cadre ", + "AbpCommercialShortDescription": "ABP Commercial fournit des modules d'application prédéfinis, des outils de développement rapide d'applications, des thèmes d'interface utilisateur professionnels, un support premium et plus encore.", + "LiveDemo": "Démo en direct", + "GetLicence": "Obtenez une licence", + "Application": "Application", + "StartupTemplates": "Modèles de démarrage", + "Startup": "Commencez", + "Templates": "Modèles", + "Developer": "Développeur", + "Tools": "Outils", + "Premium": "Premium", + "PremiumSupport": "Assistance Premium", + "PremiumForumSupport": "Assistance du forum Premium", + "UI": "UI", + "Themes": "Thèmes", + "JoinOurNewsletter": "Rejoignez notre newsletter", + "Send": "Envoyer", + "Learn": "Apprendre", + "AdditionalServices": "Des services supplémentaires", + "WhatIsABPFramework": "QU'EST-CE QUE LE FRAMEWORK ABP?", + "OpenSourceBaseFramework": "Framework de base Open Source", + "ABPFrameworkExplanation": "

ABP Commercial est basé sur ABP Framework, un framework d'applications Web open source et communautaire pour ASP.NET Core.

ABP Framework fournit une excellente infrastructure pour écrire maintenable et extensible et du code testable avec les meilleures pratiques.

Construit et intégré à des outils populaires que vous connaissez déjà. Faible courbe d'apprentissage, adaptation facile, développement confortable.

", + "Modular": "Modulaire", + "MicroserviceCompatible": "Compatible avec les microservices", + "DomainDrivenDesignInfrastructure": "Infrastructure de conception pilotée par domaine", + "MultiTenancy": "Multi-souscrivant", + "DistributedMessaging": "Messagerie distribuée", + "DynamicProxying": "Proxying dynamique", + "BackgroundJobs": "Tâches d'arrière-plan", + "AuditLogging": "Journalisation d'audit", + "BLOBStoring": "Stockage BLOB", + "BundlingMinification": "Bundling et minification", + "AdvancedLocalization": "Localisation avancée", + "ManyMore": "Beaucoup plus", + "ExploreTheABPFramework": "Explorez le Framework ABP", + "WhyUseTheABPCommercial": "Pourquoi utiliser ABP Commercial?", + "WhyUseTheABPCommercialExplanation": "

La création d'applications Web de niveau entreprise peut être complexe et prendre du temps.

ABP Commercial offre l'infrastructure de base parfaite nécessaire pour tous les ASP.NET Core modernes de niveau entreprise solutions basées. De la conception au déploiement, l'ensemble du cycle de développement est optimisé par les fonctionnalités et modules intégrés d'ABP.

", + "StartupTemplatesShortDescription": "Les modèles de démarrage vous permettent de démarrer votre projet en quelques secondes.", + "UIFrameworksOptions": "Options de frameworks d'interface utilisateur;", + "DatabaseProviderOptions": "Options du fournisseur de base de données;", + "PreBuiltApplicationModules": "Modules d'application prédéfinis", + "PreBuiltApplicationModulesShortDescription": "Les exigences d'application les plus courantes sont déjà développées pour vous en tant que modules réutilisables.", + "Account": "Compte", + "Blogging": "Bloguer", + "Identity": "Identité", + "IdentityServer": "Serveur d'identité", + "Saas": "Saas", + "LanguageManagement": "Gestion de la langue", + "TextTemplateManagement": "Gestion des modèles de texte", + "See All Modules": "VoirTousModules", + "ABPSuite": "ABP Suite", + "AbpSuiteShortDescription": "ABP Suite est un outil complémentaire à ABP Commercial.", + "AbpSuiteExplanation": "Il vous permet de créer des pages Web en quelques minutes. C'est un outil global .NET Core qui peut être installé à partir de la ligne de commande. Il peut créer une nouvelle solution ABP, générer des pages CRUD de la base de données vers le front-end.", + "Details": "Détails", + "LeptonTheme": "Thème Lepton", + "ProfessionalModernUIThemes": "Thèmes d'interface utilisateur professionnels et modernes", + "LeptonThemeExplanation": "Lepton fournit une gamme de thèmes d'administration Bootstrap qui servent de base solide pour tout projet nécessitant un tableau de bord d'administration.", + "DefaultTheme": "Thème par défaut", + "MaterialTheme": "Thème Material", + "Default2Theme": "Thème par défaut 2", + "DarkTheme": "Thème sombre", + "DarkBlueTheme": "Thème bleu foncé", + "LightTheme": "Thème clair", + "ProudToWorkWith": "Fier de travailler avec", + "OurConsumers": "Des centaines d'entreprises et de développeurs dans plus de 50 pays dans le monde font confiance à ABP Commercial.", + "JoinOurConsumers": "Rejoignez-les et créez rapidement des produits incroyables.", + "AdditionalServicesExplanation": "Avez-vous besoin de services supplémentaires ou personnalisés? Nous et nos partenaires pouvons fournir; ", + "CustomProjectDevelopment": "Développement de projets personnalisés", + "CustomProjectDevelopmentExplanation": "Développeurs dédiés pour vos projets personnalisés.", + "PortingExistingProjects": "Portage de projets existants", + "PortingExistingProjectsExplanation": "Migration de vos anciens projets vers la plateforme ABP.", + "LiveSupport": "Support en direct", + "LiveSupportExplanation": "Option d'assistance à distance en direct lorsque vous en avez besoin.", + "Training": "Formation", + "TrainingExplanation": "Une formation dédiée pour vos développeurs.", + "OnBoarding": "Intégration", + "OnBoardingExplanation": "Aide à la configuration de vos environnements de développement, CI et CD.", + "PrioritizedTechnicalSupport": "Assistance technique prioritaire", + "PremiumSupportExplanation": "Outre le grand support communautaire du framework ABP, notre équipe de support répond aux questions techniques et aux problèmes des utilisateurs commerciaux avec une priorité élevée.", + "SeeTheSupportOptions": "Voir les options de support", + "Contact": "Contacter", + "TellUsWhatYouNeed": "Dites-nous ce dont vous avez besoin.", + "YourMessage": "Votre message", + "YourFullName": "Votre nom complet", + "EmailField": "Adresse e-mail", + "YourEmailAddress": "Votre adresse email", + "HowMayWeHelpYou": "Comment pouvons nous vous aider?", + "SendMessage": "Envoyer le message", + "Success": "Succès", + "WeWillReplyYou": "Nous avons reçu votre message et vous contacterons sous peu.", + "GoHome": "Retour à l'acceuil", + "CreateLiveDemo": "Créer une démo en direct", + "RegisterToTheNewsletter": "Inscrivez-vous à la newsletter pour recevoir des informations concernant ABP.IO, y compris les nouvelles versions, etc.", + "EnterYourEmailOrLogin": "Saisissez votre adresse e-mail pour créer votre démo ou Connectez-vous à l'aide de votre compte existant.", + "ApplicationTemplate": "Modèle d'application", + "ApplicationTemplateExplanation": "Le modèle de démarrage d'application est utilisé pour créer une nouvelle application Web.", + "EfCoreProvider": "Entity Framework (prend en charge SQL Server, MySQL, PostgreSQL, Oracle et autres )", + "AlreadyIncludedInTemplateModules": "Les modules suivants sont déjà inclus et configurés dans ce modèle:", + "ApplicationTemplateArchitecture": "Ce modèle d'application prend également en charge l'architecture à plusieurs niveaux dans laquelle la couche d'interface utilisateur, la couche API et le service d'authentification sont physiquement séparés.", + "SeeTheGuideOrGoToTheLiveDemo": "Consultez le guide du développeur pour obtenir des informations techniques sur ce modèle ou accédez à la démo en direct.", + "DeveloperGuide": "Guide du développeur", + "ModuleTemplate": "Modèle de module", + "ModuleTemplateExplanation1": "Vous souhaitez créer un module et le réutiliser dans différentes applications? Ce modèle de démarrage prépare tout pour commencer à créer un module d'application réutilisable ou un microservice .", + "ModuleTemplateExplanation2": "

Vous pouvez prendre en charge un ou plusieurs frameworks d'interface utilisateur, un ou plusieurs fournisseurs de bases de données pour un seul module. Le modèle de démarrage est configuré pour exécuter et tester votre module dans une application minimale en plus de l'infrastructure de test d'unité et d'intégration.

Consultez le guide du développeur pour obtenir des informations techniques sur ce modèle.

", + "WithAllStyleOptions": "avec toutes les options de style", + "Demo": "Démo", + "SeeAllModules": "Voir tous les modules", + "ABPCLIExplanation": "ABP CLI (Command Line Interface) est un outil de ligne de commande pour effectuer certaines opérations courantes pour les solutions basées sur ABP.", + "ABPSuiteEasilyCURD": "ABP Suite est un outil qui vous permet de créer facilement des pages CRUD", + "WeAreHereToHelp": "Nous sommes ici pour Aide ", + "BrowseOrAskQuestion": "Vous pouvez parcourir nos rubriques d'aide ou rechercher dans les questions fréquemment posées, ou vous pouvez nous poser une question en utilisant le formulaire de contact .", + "SearchQuestionPlaceholder": "Rechercher dans les questions fréquemment posées", + "WhatIsTheABPCommercial": "Qu'est-ce que la publicité ABP?", + "WhatAreDifferencesThanAbpFramework": "Quelles sont les différences entre le Framework ABP open source et le ABP Commercial?", + "ABPCommercialExplanation": "ABP Commercial est un ensemble de modules, d'outils, de thèmes et de services premium basés sur le framework ABP open source. ABP Commercial est développé et soutenu par la même équipe derrière le cadre ABP.", + "WhatAreDifferencesThanABPFrameworkExplanation": "

Framework ABP est un framework de développement d'applications modulaire, thématique et compatible avec les micro-services pour ASP.NET Core. Il fournit une architecture complète et une infrastructure solide pour vous permettre de vous concentrer sur votre propre code métier plutôt que de vous répéter à chaque nouveau projet. Il est basé sur les meilleures pratiques de développement logiciel et les outils populaires que vous connaissez déjà.

Le framework ABP est entièrement gratuit, open source et géré par la communauté. Il fournit également un thème gratuit et des modules prédéfinis (par exemple, la gestion des identités et la gestion des locataires).

", + "VisitTheFrameworkVSCommercialDocument": "Pour plus d'informations, consultez le lien suivant: {1} ", + "ABPCommercialFollowingBenefits": "ABP Commercial ajoute les avantages suivants en plus du cadre ABP;", + "Professional": "Professionnel", + "UIThemes": "Thèmes de l'interface utilisateur", + "EnterpriseModules": "Des modules d'application prédéfinis, prêts pour l'entreprise, riches en fonctionnalités (par exemple, gestion d'Identity Server, gestion SaaS, gestion des langues)", + "ToolingToSupport": "Outils pour soutenir votre productivité de développement (par exemple, ABP Suite )", + "PremiumSupportLink": "Assistance Premium ", + "WhatDoIDownloadABPCommercial": "Que dois-je télécharger lorsque j'achète l'ABP Commercial?", + "CreateUnlimitedSolutions": "Une fois que vous avez acheté une licence commerciale ABP, vous pourrez créer des solutions illimitées comme décrit dans le document Premiers pas .", + "ABPCommercialSolutionExplanation": "Lorsque vous créez une nouvelle application, vous obtenez une solution Visual Studio (un modèle de démarrage) en fonction de vos préférences. La solution téléchargée contient des modules et des thèmes commerciaux déjà installés et configurés pour vous. Vous pouvez supprimer un module préinstallé ou ajouter un autre module si vous le souhaitez. Tous les modules et thèmes sont utilisés par défaut dans des packages NuGet / NPM.", + "StartDevelopWithTutorials": "La solution téléchargée est bien architecturée et documentée. Vous pouvez commencer à développer votre propre code d'entreprise basé sur celui-ci en suivant les didacticiels ", + "TryTheCommercialDemo": "Vous pouvez essayer la démonstration pour voir un exemple d'application créé à l'aide du modèle de démarrage ABP Commercial.", + "HowManyProducts": "Combien de produits / solutions différents puis-je créer à l'aide d'ABP Commercial?", + "HowManyProductsExplanation": "Il n'y a pas de limite pour créer un projet ABP. Vous pouvez créer autant de projets que vous le souhaitez, les développer et les télécharger sur différents serveurs.", + "HowManyDevelopers": "Combien de développeurs peuvent travailler sur l'ABP Commercial?", + "HowManyDevelopersExplanation": "Les licences commerciales ABP sont par développeur. Différents types de licence ont des limites de développeur différentes. Cependant, vous pouvez ajouter plus de développeurs à n'importe quel type de licence chaque fois que vous en avez besoin. Consultez la page des prix pour connaître les types de licence, les limites pour les développeurs et les coûts supplémentaires pour les développeurs.", + "ChangingLicenseType": "Puis-je changer mon type de licence à l'avenir?", + "ChangingLicenseTypeExplanation": "Vous pouvez toujours ajouter de nouveaux développeurs dans votre même type de licence. Voir aussi \"Combien de développeurs peuvent travailler sur l'ABP Commercial?\". Vous pouvez également passer à une licence supérieure en payant la différence de prix calculée. Lorsque vous passez à un plan de licence supérieur, vous bénéficiez des avantages du nouveau plan, mais la mise à niveau de la licence ne modifie pas la date d'expiration de la licence.", + "LicenseExtendUpgradeDiff": "Quelle est la différence entre l'extension de licence et la mise à niveau?", + "LicenseExtendUpgradeDiffExplanation": " Extension: en prolongeant / renouvelant votre licence, vous continuerez à bénéficier d'une assistance premium et à des mises à jour majeures pour les modules et les thèmes. De plus, vous pourrez continuer à créer de nouveaux projets. Et vous pourrez toujours utiliser ABP Suite, ce qui accélère votre développement.
Mise à niveau: En mettant à jour votre licence, vous passerez à un plan de licence supérieur qui vous permettra d’obtenir des avantages supplémentaires . Consultez le tableau de comparaison des licences pour vérifier les différences entre les plans de licence. En revanche, lors de la mise à niveau, la date d'expiration de votre licence ne changera pas! Pour prolonger la date de fin de votre licence, vous devez prolonger votre licence.", + "LicenseRenewalCost": "Quel est le coût du renouvellement de la licence après 1 an?", + "LicenseRenewalCostExplanation": "Le taux de renouvellement (extension) de toutes les licences perpétuelles ABP Commercial correspond à {0} du prix catalogue de la licence. Le prix de renouvellement de la licence d'équipe standard est de {1} $, la licence professionnelle standard de {2} $ et la licence d'entreprise standard de {3} $. Si vous êtes déjà client, connectez-vous à votre compte pour consulter les tarifs de renouvellement disponibles.", + "HowDoIRenewMyLicense": "Comment renouveler ma licence?", + "HowDoIRenewMyLicenseExplanation": "Vous pouvez renouveler votre licence en accédant à la page de gestion de l'organisation . Afin de profiter de nos tarifs réduits de renouvellement anticipé, assurez-vous de renouveler avant l'expiration de votre licence. Cependant, ne vous inquiétez pas de ne pas savoir quand votre opportunité de renouvellement anticipé se termine. Vous recevrez 2 e-mails de rappel avant l'expiration de votre abonnement. Nous les enverrons dans les 30 jours, 7 jours avant l'expiration.", + "IsSourceCodeIncluded": "Ma licence inclut-elle le code source des modules et thèmes commerciaux?", + "IsSourceCodeIncludedExplanation1": "Dépend du type de licence que vous avez acheté:", + "IsSourceCodeIncludedExplanation2": " Équipe : votre solution utilise les modules et les thèmes en tant que packages NuGet et NPM. Il n'inclut pas leur code source. De cette façon, vous pouvez facilement mettre à niveau ces modules et thèmes chaque fois qu'une nouvelle version est disponible. Cependant, vous ne pouvez pas obtenir le code source des modules et des thèmes.", + "IsSourceCodeIncludedExplanation3": " Entreprise / Entreprise : en plus de la licence Team, vous pouvez télécharger le code source de tout module ou thème dont vous avez besoin. Vous pouvez même supprimer les références de package NuGet / NPM pour un module particulier et ajouter son code source directement à votre solution pour le modifier complètement.", + "IsSourceCodeIncludedExplanation4": "

L'inclusion du code source d'un module dans votre solution vous donne le maximum de liberté pour personnaliser ce module. Cependant, il ne sera pas possible de mettre à jour automatiquement le module lorsqu'une nouvelle version est publiée.

Aucune des licences n'inclut le code source d'ABP Suite, qui est un outil externe qui génère du code pour vous et vous aide à votre développement.

Consultez la page de tarification pour connaître les autres différences entre les types de licence.

", + "ChangingDevelopers": "Puis-je changer les développeurs enregistrés de mon organisation à l'avenir?", + "ChangingDevelopersExplanation": "En plus d'ajouter de nouveaux développeurs à votre licence, vous pouvez également modifier les développeurs existants (vous pouvez supprimer un développeur et en ajouter un nouveau sur le même siège) sans aucun coût supplémentaire.", + "WhatHappensWhenLicenseEnds": "Que se passe-t-il à la fin de ma période de licence?", + "WhatHappensWhenLicenseEndsExplanation1": "Le type de licence commerciale ABP est licence perpétuelle . Une fois votre licence expirée, vous pouvez continuer à développer votre projet. Et vous n'êtes pas obligé de renouveler votre licence. Votre licence est livrée avec un plan de mise à jour et de support d'un an prêt à l'emploi. Pour continuer à recevoir de nouvelles fonctionnalités, des améliorations de performances, des corrections de bogues, une assistance et continuer à utiliser ABP Suite, assurez-vous de renouveler votre plan chaque année. Lorsque votre licence expirera, vous ne pourrez plus bénéficier des avantages suivants;", + "WhatHappensWhenLicenseEndsExplanation2": "Vous ne pouvez pas créer de nouvelles solutions en utilisant ABP Commercial, mais vous pouvez continuer à développer vos applications existantes pour toujours.", + "WhatHappensWhenLicenseEndsExplanation3": "Vous pourrez obtenir des mises à jour pour les modules et les thèmes de votre version MAJEURE. Par example; si vous utilisez la v3.2.0 d'un module, vous pouvez toujours obtenir des mises à jour pour la v3.x.x (v3.3.0, v3.5.2 ... etc.) de ce module. Mais vous ne pouvez pas obtenir de mises à jour pour la prochaine version majeure (comme v4.x, v5.x)", + "WhatHappensWhenLicenseEndsExplanation4": "Vous ne pouvez pas installer de nouveaux modules et thèmes ajoutés à la plate-forme ABP Commercial après la fin de votre licence.", + "WhatHappensWhenLicenseEndsExplanation5": "Vous ne pouvez pas utiliser ABP Suite.", + "WhatHappensWhenLicenseEndsExplanation6": "Vous ne pouvez plus bénéficier de l ' assistance premium .", + "WhatHappensWhenLicenseEndsExplanation7": "Vous pouvez renouveler votre abonnement si vous souhaitez continuer à bénéficier de ces avantages. Il y a une réduction de 20% lorsque vous renouvelez votre abonnement.", + "WhenShouldIRenewMyLicense": "Quand dois-je renouveler ma licence?", + "WhenShouldIRenewMyLicenseExplanation1": "Si vous renouvelez votre licence dans un délai de 1 mois après l'expiration de votre licence, une réduction de 20% sera appliquée au prix total de la licence.", + "WhenShouldIRenewMyLicenseExplanation2": "Si vous renouvelez votre licence 1 mois après la date d'expiration de votre licence, le prix de renouvellement sera le même que le prix d'achat de la licence et il n'y aura pas de réduction pour votre renouvellement.", + "TrialPlan": "Avez-vous un plan d'essai?", + "TrialPlanExplanation": "Pour l'instant, ABP Commercial n'a pas de plan d'essai. Pour les licences Team, nous offrons une garantie de remboursement de 30 jours. Vous pouvez simplement demander un remboursement dans les 30 premiers jours. Pour les licences Business et Enterprise, nous fournissons un remboursement de 60% en 30 jours. En effet, les licences Business et Enterprise incluent le code source complet de tous les modules et thèmes.", + "DoYouAcceptBankWireTransfer": "Acceptez-vous les virements bancaires?", + "DoYouAcceptBankWireTransferExplanation": "Oui, nous acceptons les virements bancaires.
Après avoir envoyé le montant de la licence par virement bancaire, envoyez-nous votre reçu et le type de licence demandé par e-mail.
Nos coordonnées bancaires internationales:", + "HowToUpgrade": "Comment mettre à niveau des applications existantes lorsqu'une nouvelle version est disponible?", + "HowToUpgradeExplanation1": "Lorsque vous créez une nouvelle application à l'aide d'ABP Commercial, tous les modules et le thème sont utilisés en tant que packages NuGet et NPM. Ainsi, vous pouvez facilement mettre à jour les packages lorsqu'une nouvelle version est disponible.", + "HowToUpgradeExplanation2": "Outre les mises à niveau standard de NuGet / NPM, ABP CLI fournit une commande de mise à jour qui recherche et met automatiquement à niveau tous les packages associés à ABP dans votre solution.", + "DatabaseSupport": "Quels systèmes de base de données sont pris en charge?", + "DatabaseSupportExplanation": "ABP Framework lui-même est indépendant de la base de données et peut fonctionner avec n'importe quel fournisseur de base de données de par sa nature. Consultez le document d'accès aux données pour obtenir la liste des fournisseurs actuellement mis en œuvre.", + "UISupport": "Quels frameworks d'interface utilisateur sont pris en charge?", + "Supported": "Prise en charge", + "UISupportExplanation": "ABP Framework lui-même est indépendant du framework d'interface utilisateur et peut fonctionner avec n'importe quel framework d'interface utilisateur. Cependant, les modèles de démarrage, les interfaces utilisateur de module et les thèmes n'étaient pas implémentés pour tous les frameworks d'interface utilisateur. Consultez le document de démarrage pour la liste à jour des options d'interface utilisateur.", + "MicroserviceSupport": "Prend-il en charge l'architecture des micro-services?", + "MicroserviceSupportExplanation1": "L'un des principaux objectifs du cadre ABP est de fournir une infrastructure pratique pour créer des solutions de micro-services. Consultez le document architecture de micro-service pour comprendre comment cela aide à créer des systèmes de micro-service.", + "MicroserviceSupportExplanation2": "Tous les modules ABP Commercial sont conçus pour prendre en charge les scénarios de déploiement de micro-services (avec sa propre API et sa propre base de données) en suivant le document bonnes pratiques de développement de modules .", + "MicroserviceSupportExplanation3": "Nous fournissons un exemple de solution de démonstration de micro-service qui présente une implémentation d'architecture de micro-service pour vous aider à créer votre propre solution.", + "MicroserviceSupportExplanation4": "Donc, la réponse courte est \" oui, il prend en charge l'architecture de micro-services \".", + "MicroserviceSupportExplanation5": "Cependant, un système de micro-service est une solution et chaque solution aura des exigences différentes, une topologie de réseau, des scénarios de communication, des possibilités d'authentification, des décisions de séparation / partage de base de données, des configurations d'exécution, des intégrations de systèmes tiers et bien d'autres.", + "MicroserviceSupportExplanation6": "Le Framework ABP et l'ABP Commercial fournissent une infrastructure pour des scénarios de micro-services, des modules compatibles avec les micro-services, des exemples et de la documentation pour vous aider à créer votre propre solution. Mais ne vous attendez pas à télécharger directement la solution de vos rêves préconfigurée pour vous. Vous devrez le comprendre et rassembler certaines parties en fonction de vos besoins.", + "WhereCanIDownloadSourceCode": "Où puis-je télécharger le code source?", + "WhereCanIDownloadSourceCodeExplanation": "Vous pouvez télécharger le code source de tous les modules ABP, packages angulaires et thèmes via ABP Suite ou ABP CLI. Voir Comment télécharger le code source? ", + "ComputerLimitation": "Combien d'ordinateurs un développeur peut-il se connecter lors du développement d'ABP?", + "ComputerLimitationExplanation": "Nous autorisons spécifiquement les {0} ordinateurs par développeur individuel / sous licence. Chaque fois qu'un développeur a besoin de développer des produits commerciaux ABP sur une troisième machine, un e-mail doit être envoyé à license@abp.io expliquant la situation et nous procéderons ensuite à l'allocation appropriée dans notre système.", + "RefundPolicy": "Avez-vous une politique de remboursement?", + "RefundPolicyExplanation": "Vous pouvez demander un remboursement dans les 30 jours suivant l'achat de votre licence. Les types de licence Business et Enterprise ont une option de téléchargement de code source, par conséquent, les remboursements ne sont pas disponibles pour les entreprises et les entreprises (et toutes les licences qui incluent un droit de recevoir le code source). De plus, aucun remboursement n'est effectué pour les renouvellements et les achats de deuxième licence.", + "HowCanIRefundVat": "Comment puis-je rembourser la TVA?", + "HowCanIRefundVatExplanation1": "Si vous avez effectué le paiement avec 2Checkout, vous pouvez rembourser la TVA via votre compte 2Checkout:", + "HowCanIRefundVatExplanation2": "Connectez-vous à votre compte 2Checkout ", + "HowCanIRefundVatExplanation3": "Trouvez la commande appropriée et appuyez sur \"Rembourser la TVA tardive\" (entrez votre numéro de TVA)", + "HowCanIGetMyInvoice": "Comment puis-je obtenir ma facture?", + "HowCanIGetMyInvoiceExplanation": "Il existe 2 passerelles de paiement pour l'achat d'une licence: PayU et 2Checkout. Si vous achetez votre licence via la passerelle 2Checkout, elle envoie la facture PDF à votre adresse e-mail, voir Facturation 2Checkout. Si vous achetez via la passerelle PayU ou par virement bancaire, nous préparerons et vous enverrons votre facture. Vous pouvez demander votre facture sur la page de gestion de l'organisation. ", + "Forum": "Forum", + "SupportExplanation": "ABP Commercial Licences fournit un support de forum premium par une équipe composée d'experts ABP Framework.", + "PrivateTicket": "Billet privé", + "PrivateTicketExplanation": "Enterprise License comprend également un support privé avec e-mail et système de ticket.", + "AbpSuiteExplanation1": "ABP Suite vous permet de créer des pages Web en quelques minutes. C'est un outil .NET Core Global qui peut être installé à partir de la ligne de commande.", + "AbpSuiteExplanation2": "Il peut créer une nouvelle solution ABP, générer des pages CRUD de la base de données vers le front-end. Pour une présentation technique, consultez le document ", + "FastEasy": "Rapide et facile", + "AbpSuiteExplanation3": "ABP Suite vous permet de créer facilement des pages CRUD. Il vous suffit de définir votre entité et ses propriétés, laissez le reste à ABP Suite pour vous! ABP Suite génère tout le code nécessaire pour votre page CRUD en quelques secondes. Il prend en charge les interfaces utilisateur Angular, MVC et Blazor.", + "RichOptions": "Options riches", + "AbpSuiteExplanation4": "ABP Suite prend en charge plusieurs options d'interface utilisateur telles que Razor Pages et Angular . Il prend également en charge plusieurs bases de données telles que MongoDB et toutes les bases de données prises en charge par EntityFramework Core < / strong> (MS SQL Server, Oracle, MySql, PostgreSQL et plus ).", + "AbpSuiteExplanation5": "La bonne chose est que vous n'avez pas à vous soucier de ces options. ABP Suite comprend votre type de projet et génère le code de votre projet et place le code généré au bon endroit dans votre projet.", + "SourceCode": "Code source", + "AbpSuiteExplanation6": "ABP Suite génère le code source pour vous! Il ne génère pas de fichiers magiques pour générer la page Web. ABP Suite génère le code source pour Entity, Repository, Application Service, Code First Migration, JavaScript / TypeScript et CSHTML / HTML ainsi que les interfaces nécessaires. ABP Suite génère également le code selon les meilleures pratiques de développement logiciel, vous n'avez donc pas à vous soucier de la qualité du code généré.", + "AbpSuiteExplanation7": "Puisque vous avez le code source des blocs de construction de la page CRUD générée dans les couches d'application correctes, vous pouvez facilement modifier le code source et injecter votre logique personnalisée / commerciale dans le code généré.", + "CrossPlatform": "Plateforme croisée", + "AbpSuiteExplanation8": "ABP Suite est construit avec .NET Core et est multiplateforme. Il fonctionne comme une application Web sur votre ordinateur local. Vous pouvez l'exécuter sur Windows , Mac et Linux ", + "OtherFeatures": "Autres caractéristiques", + "OtherFeatures1": "Met à jour facilement les packages NuGet et NPM de votre solution.", + "OtherFeatures2": "Régénère les pages déjà générées à partir de zéro.", + "OtherFeatures3": "Crée de nouvelles solutions", + "ThanksForCreatingProject": "Merci d'avoir créé votre projet!", + "HotToRunSolution": "Comment faire fonctionner votre solution?", + "HotToRunSolutionExplanation": "Consultez le document de mise en route pour savoir comment configurer et exécuter votre solution.", + "GettingStarted": "Commencer", + "WebAppDevTutorial": "Tutoriel de développement d'applications Web", + "WebAppDevTutorialExplanation": "Consultez le document du didacticiel de développement d'applications Web pour un exemple de développement étape par étape.", + "Document": "Document", + "UsingABPSuiteToCURD": "Utilisation d'ABP Suite pour la génération et l'outillage de pages CRUD", + "SeeABPSuiteDocument": "Consultez le document ABP Suite pour en savoir plus sur l'utilisation d'ABP Suite.", + "AskQuestionsOnSupport": "Vous pouvez poser des questions sur le support commercial ABP.", + "Documentation": "Documentation", + "SeeModulesDocument": "Voir le document des modules pour une liste de tous les modules commerciaux (pro) et leurs documents.", + "Pricing": "Tarification", + "PricingExplanation": "Choisissez les fonctionnalités dont votre entreprise a besoin aujourd'hui. Mettez à niveau facilement au fur et à mesure que votre entreprise se développe.", + "Team": "Équipe", + "Business": "Affaires", + "Enterprise": "Entreprise", + "Custom": "Personnalisé", + "IncludedDeveloperLicenses": "Licences de développeur incluses", + "CustomLicenceOrAdditionalServices": "Besoin d'une licence personnalisée ou de services supplémentaires?", + "CustomOrVolumeLicense": "Licence personnalisée ou en volume", + "LiveTrainingSupport": "Formation et assistance en direct", + "AndMore": "et plus", + "AdditionalDeveloperLicense": "Licence de développeur supplémentaire", + "ProjectCount": "Nombre de projets", + "AllProModules": "Tous les modules pro", + "AllProThemes": "Tous les thèmes pro", + "AllProStartupTemplates": "Tous les modèles de démarrage pro", + "SourceCodeOfAllModules": "Code source de tous les modules", + "SourceCodeOfAllThemes": "Code source de tous les thèmes", + "PerpetualLicense": "Licence perpétuelle", + "UnlimitedServerDeployment": "Déploiement de serveur illimité", + "YearUpgrade": "Mise à jour d'un an", + "YearPremiumForumSupport": "1 an de support premium pour le forum", + "ForumSupportIncidentCountYear": "Nombre d'incidents de support du forum / an", + "PrivateTicketEmailSupport": "Support privé pour les tickets et e-mail", + "BuyNow": "Acheter maintenant", + "PayViaAmexCard": "Comment puis-je payer via ma carte AMEX?", + "PayViaAmexCardDescription": "La passerelle de paiement par défaut «Iyzico» peut refuser certaines cartes de crédit AMEX en raison des mesures de sécurité. Dans ce cas, vous pouvez payer via la passerelle de paiement alternative «2Checkout».", + "ThankYou": "Merci", + "InvalidReCaptchaErrorMessage": "Une erreur s'est produite lors de la vérification de reCAPTCHA. Veuillez réessayer." + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json new file mode 100644 index 0000000000..54216f7719 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json @@ -0,0 +1,296 @@ +{ + "culture": "hi", + "texts": { + "OrganizationManagement": "संगठन का प्रबंधन", + "OrganizationList": "संगठन सूची", + "Volo.AbpIo.Commercial:010003": "आप इस संगठन के मालिक नहीं हैं!", + "OrganizationNotFoundMessage": "कोई संगठन नहीं मिला!", + "DeveloperCount": "आवंटित / कुल डेवलपर्स", + "QuestionCount": "शेष / कुल प्रश्न", + "Unlimited": "असीमित", + "Owners": "मालिकों", + "AddMember": "सदस्य जोड़ें", + "AddOwner": "मालिक जोड़ें", + "AddDeveloper": "डेवलपर जोड़ें", + "UserName": "उपयोगकर्ता नाम", + "Name": "नाम", + "EmailAddress": "ईमेल पता", + "Developers": "डेवलपर्स", + "LicenseType": "लाइसेंस के प्रकार", + "Manage": "प्रबंधित", + "StartDate": "आरंभ करने की तिथि", + "EndDate": "समाप्ति तिथि", + "Modules": "मॉड्यूल", + "LicenseExtendMessage": "आपकी लाइसेंस समाप्ति तिथि {0} तक बढ़ा दी गई है", + "LicenseUpgradeMessage": "आपका लाइसेंस {0} में अपग्रेड किया गया है", + "LicenseAddDeveloperMessage": "{0} डेवलपर्स ने आपके लाइसेंस में जोड़ा", + "Volo.AbpIo.Commercial:010004": "निर्दिष्ट उपयोगकर्ता नहीं मिल सकता है! उपयोगकर्ता को पहले से ही पंजीकृत होना चाहिए।", + "MyOrganizations": "मेरे संगठन", + "ApiKey": "एपीआई कुंजी", + "UserNameNotFound": "उपयोगकर्ता नाम {0} का कोई उपयोगकर्ता नहीं है", + "SuccessfullyAddedToNewsletter": "हमारे न्यूज़लेटर की सदस्यता के लिए धन्यवाद!", + "MyProfile": "मेरी प्रोफाइल", + "EmailNotValid": "कृपया एक वैध ई - मेल एड्रेस डालें।", + "JoinOurMarketingNewsletter": "हमारे विपणन समाचार पत्र में शामिल हों", + "WouldLikeToReceiveMarketingMaterials": "मैं उत्पाद सौदों और विशेष प्रस्तावों जैसे विपणन सामग्री प्राप्त करना चाहता हूं।", + "StartUsingYourLicenseNow": "अब अपने लाइसेंस का उपयोग शुरू करें!", + "WelcomePage": "स्वागत पृष्ठ", + "UnsubscriptionExpireEmail": "लाइसेंस समाप्ति तिथि अनुस्मारक ईमेल से सदस्यता समाप्त करें", + "UnsubscribeLicenseExpireEmailReminderMessage": "इस ईमेल सदस्यता में केवल आपकी लाइसेंस समाप्ति तिथि याद दिलाने की होती है।", + "UnsubscribeFromLicenseExpireEmails": "यदि आप अपने लाइसेंस की समाप्ति तिथि के बारे में ईमेल प्राप्त नहीं करना चाहते हैं, तो आप किसी भी समय अपनी सदस्यता समाप्त कर सकते हैं।", + "Unsubscribe": "सदस्यता रद्द", + "NotOrganizationMember": "आप किसी संगठन के सदस्य नहीं हैं।", + "UnsubscribeLicenseExpirationEmailSuccessTitle": "सफलतापूर्वक सदस्यता समाप्त कर दी गई", + "UnsubscribeLicenseExpirationEmailSuccessMessage": "अब आपको लाइसेंस समाप्ति तिथि अनुस्मारक ईमेल प्राप्त नहीं होंगे।", + "IndexPageHeroSection": " एक पूर्ण वेब विकास मंच अंतर्निहित ढांचा ", + "AbpCommercialShortDescription": "एबीपी कमर्शियल प्री-बिल्ट एप्लिकेशन मॉड्यूल, रैपिड एप्लिकेशन डेवलपमेंट टूलिंग, पेशेवर यूआई थीम, प्रीमियम सपोर्ट आदि प्रदान करता है।", + "LiveDemo": "लाइव डेमो", + "GetLicence": "एक लाइसेंस प्राप्त करें", + "Application": "आवेदन", + "StartupTemplates": "स्टार्टअप टेम्पलेट", + "Startup": "चालू होना", + "Templates": "टेम्पलेट्स", + "Developer": "डेवलपर", + "Tools": "उपकरण", + "Premium": "प्रीमियम", + "PremiumSupport": "प्रीमियम सहायता", + "PremiumForumSupport": "प्रीमियम फोरम समर्थन", + "UI": "यूआई", + "Themes": "विषयों", + "JoinOurNewsletter": "हमारे समाचार पत्र शामिल हों", + "Send": "संदेश", + "Learn": "सीखना", + "AdditionalServices": "अतिरिक्त सेवाएं", + "WhatIsABPFramework": "ABP फ्रेमवर्क क्या है?", + "OpenSourceBaseFramework": "ओपन सोर्स बेस फ्रेमवर्क", + "ABPFrameworkExplanation": "

ABP कमर्शियल ASP.NET Core पर एक खुला स्रोत और समुदाय संचालित वेब एप्लीकेशन फ्रेमवर्क है। और सर्वोत्तम प्रथाओं के साथ परीक्षण योग्य कोड।

आप पहले से ही जानते हैं कि लोकप्रिय उपकरणों पर निर्मित और एकीकृत। कम सीखने की अवस्था, आसान अनुकूलन, आरामदायक विकास। ", + "Modular": "मॉड्यूलर", + "MicroserviceCompatible": "माइक्रोसिस्ट सेवा संगत", + "DomainDrivenDesignInfrastructure": "डोमेन संचालित डिज़ाइन इन्फ्रास्ट्रक्चर", + "MultiTenancy": "बहु किरायेदारी", + "DistributedMessaging": "वितरित संदेश", + "DynamicProxying": "गतिशील प्रॉक्सी", + "BackgroundJobs": "बैकग्राउंड जॉब्स", + "AuditLogging": "ऑडिट लॉगिंग", + "BLOBStoring": "ब्लॉब भंडारण", + "BundlingMinification": "बंडलिंग और न्यूनतमकरण", + "AdvancedLocalization": "उन्नत स्थानीयकरण", + "ManyMore": "बहुत सारी", + "ExploreTheABPFramework": "ABP फ्रेमवर्क का अन्वेषण करें", + "WhyUseTheABPCommercial": "एबीपी कमर्शियल का उपयोग क्यों करें?", + "WhyUseTheABPCommercialExplanation": "

बिल्डिंग एंटरप्राइज-ग्रेड वेब एप्लिकेशन जटिल और समय लेने वाली हो सकती हैं।

ABP कमर्शियल सभी आधुनिक एंटरप्राइज-ग्रेड ASP.NET Core के लिए आवश्यक सही आधारभूत संरचना प्रदान करता है। आधारित समाधान। डिज़ाइन से परिनियोजन तक, संपूर्ण विकास चक्र ABP की अंतर्निहित विशेषताओं और मॉड्यूल द्वारा सशक्त है। हम और हमारे साथी प्रदान कर सकते हैं; ", + "CustomProjectDevelopment": "कस्टम परियोजना विकास", + "CustomProjectDevelopmentExplanation": "अपने कस्टम प्रोजेक्ट्स के लिए समर्पित डेवलपर्स।", + "PortingExistingProjects": "मौजूदा परियोजनाओं को पोर्ट करना", + "PortingExistingProjectsExplanation": "एबीपी प्लेटफॉर्म पर अपनी विरासत परियोजनाओं को माइग्रेट करना।", + "LiveSupport": "लाइव सहायता", + "LiveSupportExplanation": "जरूरत पड़ने पर लाइव रिमोट सपोर्ट का विकल्प।", + "Training": "प्रशिक्षण", + "TrainingExplanation": "अपने डेवलपर्स के लिए समर्पित प्रशिक्षण।", + "OnBoarding": "ज्ञानप्राप्ति", + "OnBoardingExplanation": "अपने विकास, CI और सीडी वातावरण को सेटअप करने में मदद करें।", + "PrioritizedTechnicalSupport": "प्राथमिक तकनीकी सहायता", + "PremiumSupportExplanation": "एबीपी ढांचे के महान सामुदायिक समर्थन के अलावा, हमारी सहायता टीम उच्च प्राथमिकता वाले वाणिज्यिक उपयोगकर्ताओं की तकनीकी सवालों और समस्याओं का जवाब देती है।", + "SeeTheSupportOptions": "समर्थन विकल्प देखें", + "Contact": "संपर्क करें", + "TellUsWhatYouNeed": "अपनी ज़रूरत के बारे में हमें बताएं।", + "YourMessage": "आपका संदेश", + "YourFullName": "आपका पूरा नाम", + "EmailField": "ईमेल पता", + "YourEmailAddress": "आपका ईमेल पता", + "HowMayWeHelpYou": "हम कैसे आपकी सहायता कर सकते हैं?", + "SendMessage": "मेसेज भेजें", + "Success": "सफलता", + "WeWillReplyYou": "हमें आपका संदेश प्राप्त हुआ और शीघ्र ही संपर्क में आएगा।", + "GoHome": "घर जाओ", + "CreateLiveDemo": "लाइव डेमो बनाएँ", + "RegisterToTheNewsletter": "ABP.IO के बारे में जानकारी प्राप्त करने के लिए न्यूज़लेटर के लिए रजिस्टर करें, जिसमें नई रिलीज़ आदि शामिल हैं।", + "EnterYourEmailOrLogin": "अपने मौजूदा खाते का उपयोग करके अपना डेमो बनाने के लिए अपना ई-मेल पता दर्ज करें या अपना प्रदर्शन लॉगिन करें।", + "ApplicationTemplate": "एप्लिकेशन टेम्पलेट", + "ApplicationTemplateExplanation": "एप्लिकेशन स्टार्टअप टेम्पलेट का उपयोग एक नया वेब एप्लिकेशन बनाने के लिए किया जाता है।", + "EfCoreProvider": "इकाई ढाँचा (SQL सर्वर, MySQL, PostgreSQL, Oracle और अन्य का समर्थन करता है)", + "AlreadyIncludedInTemplateModules": "निम्नलिखित मॉड्यूल पहले से ही इस टेम्पलेट में शामिल और कॉन्फ़िगर किए गए हैं:", + "ApplicationTemplateArchitecture": "यह एप्लिकेशन टेम्पलेट tiered आर्किटेक्चर का भी समर्थन करता है जहां UI लेयर, API लेयर और ऑथेंटिकेशन सर्विस को शारीरिक रूप से अलग किया जाता है।", + "SeeTheGuideOrGoToTheLiveDemo": "इस टेम्पलेट के बारे में तकनीकी जानकारी के लिए डेवलपर गाइड देखें या लाइव डेमो पर जाएं।", + "DeveloperGuide": "डेवलपर गाइड", + "ModuleTemplate": "मॉड्यूल टेम्पलेट", + "ModuleTemplateExplanation1": "आप एक मॉड्यूल बनाना और विभिन्न अनुप्रयोगों में पुन: उपयोग करना चाहते हैं? यह स्टार्टअप टेम्पलेट एक पुन: प्रयोज्य अनुप्रयोग मॉड्यूल या microservice बनाने के लिए शुरू करने के लिए सब कुछ तैयार करता है।", + "ModuleTemplateExplanation2": "

आप एकल मॉड्यूल के लिए एकल या एकाधिक UI फ्रेमवर्क, एकल या एकाधिक डेटाबेस प्रदाता का समर्थन कर सकते हैं। स्टार्टअप टेम्प्लेट को चलाने के लिए कॉन्फ़िगर किया गया है और अपने मॉड्यूल का परीक्षण करें यूनिट और एकीकरण परीक्षण के बुनियादी ढांचे के अलावा न्यूनतम आवेदन में।

इस टेम्पलेट के बारे में तकनीकी जानकारी के लिए डेवलपर गाइड देखें। ", + "WithAllStyleOptions": "सभी शैली विकल्पों के साथ", + "Demo": "डेमो", + "SeeAllModules": "सभी मॉड्यूल देखें", + "ABPCLIExplanation": "ABP CLI (कमांड लाइन इंटरफेस) ABP आधारित समाधानों के लिए कुछ सामान्य ऑपरेशन करने के लिए एक कमांड लाइन टूल है।", + "ABPSuiteEasilyCURD": "एबीपी सूट एक उपकरण है जो आपको आसानी से CRUD पेज बनाने की अनुमति देता है", + "WeAreHereToHelp": "हम यहाँ हैं मदद ", + "BrowseOrAskQuestion": "आप हमारे सहायता विषयों को ब्राउज़ कर सकते हैं या अक्सर पूछे जाने वाले प्रश्नों में खोज कर सकते हैं, या आप संपर्क फ़ॉर्म का उपयोग करके हमसे एक प्रश्न पूछ सकते हैं।", + "SearchQuestionPlaceholder": "अक्सर पूछे जाने वाले प्रश्नों में खोजें", + "WhatIsTheABPCommercial": "ABP कमर्शियल क्या है?", + "WhatAreDifferencesThanAbpFramework": "ओपन सोर्स ABP फ्रेमवर्क और ABP कमर्शियल के बीच क्या अंतर हैं?", + "ABPCommercialExplanation": "एबीपी कमर्शियल, खुले स्रोत के शीर्ष पर बनाए गए प्रीमियम मॉड्यूल, टूल, थीम और सेवाओं का एक सेट है जो ABP फ्रेमवर्क है। एबीपी कमर्शियल को एबीपी फ्रेमवर्क के पीछे उसी टीम द्वारा विकसित और समर्थित किया जा रहा है।", + "WhatAreDifferencesThanABPFrameworkExplanation": "

ABP फ्रेमवर्क ASP.NET Core के लिए एक मॉड्यूलर, थीमेबल, माइक्रो-सर्विस संगत एप्लिकेशन डेवलपमेंट फ्रेमवर्क है। यह आपको हर नई परियोजना के लिए खुद को दोहराने के बजाय अपने खुद के व्यवसाय कोड पर ध्यान केंद्रित करने के लिए एक पूर्ण वास्तुकला और एक मजबूत बुनियादी ढांचा प्रदान करता है। यह सॉफ्टवेयर विकास सर्वोत्तम प्रथाओं और लोकप्रिय उपकरणों पर आधारित है जिन्हें आप पहले से जानते हैं।

एबीपी फ्रेमवर्क पूरी तरह से मुक्त, खुला स्रोत और समुदाय-संचालित है। यह एक मुफ्त थीम और कुछ पूर्व-निर्मित मॉड्यूल (जैसे पहचान प्रबंधन और किरायेदार प्रबंधन) प्रदान करता है। ", + "VisitTheFrameworkVSCommercialDocument": "अधिक जानकारी के लिए, निम्न लिंक पर जाएं {1} ", + "ABPCommercialFollowingBenefits": "एबीपी वाणिज्यिक एबीपी ढांचे के शीर्ष पर निम्नलिखित लाभ जोड़ता है;", + "Professional": "पेशेवर", + "UIThemes": "यूआई थीम", + "EnterpriseModules": "एंटरप्राइज रेडी, फीचर से भरपूर, पहले से निर्मित एप्लिकेशन मॉड्यूल (जैसे पहचान सर्वर प्रबंधन, सास प्रबंधन, भाषा प्रबंधन)", + "ToolingToSupport": "अपनी विकास उत्पादकता का समर्थन करने का टूल", + "PremiumSupportLink": "प्रीमियम समर्थन ", + "WhatDoIDownloadABPCommercial": "जब मैं एबीपी कमर्शियल खरीदता हूं तो क्या डाउनलोड करता हूं?", + "CreateUnlimitedSolutions": "एक बार जब आप एक एबीपी कमर्शियल लाइसेंस खरीदते हैं, तो आप असीमित समाधान बना पाएंगे, जैसे कि Get Started दस्तावेज़ में वर्णित है।", + "ABPCommercialSolutionExplanation": "जब आप एक नया एप्लिकेशन बनाते हैं, तो आपको अपनी प्राथमिकताओं के आधार पर एक विज़ुअल स्टूडियो समाधान (एक स्टार्टअप टेम्प्लेट) मिलता है। डाउनलोड किए गए समाधान में आपके लिए पहले से इंस्टॉल और कॉन्फ़िगर किए गए वाणिज्यिक मॉड्यूल और थीम हैं। यदि आप चाहें तो आप पहले से स्थापित मॉड्यूल को हटा सकते हैं या किसी अन्य मॉड्यूल को जोड़ सकते हैं। सभी मॉड्यूल और थीम डिफ़ॉल्ट रूप से एक NuGet / NPM पैकेज का उपयोग किया जाता है।", + "StartDevelopWithTutorials": "डाउनलोड किया गया समाधान अच्छी तरह से वास्तुकला और दस्तावेज है। आप अपने स्वयं के व्यवसाय कोड को इस आधार पर विकसित करना शुरू कर सकते हैं कि वह ट्यूटोरियल्स का अनुसरण कर सकता है", + "TryTheCommercialDemo": "ABP कमर्शियल स्टार्टअप टेम्प्लेट का उपयोग करके बनाए गए एक नमूना अनुप्रयोग को देखने के लिए आप डेमो का प्रयास कर सकते हैं।", + "HowManyProducts": "ABP वाणिज्यिक का उपयोग करके मैं कितने विभिन्न उत्पाद / समाधान बना सकता हूं?", + "HowManyProductsExplanation": "ABP प्रोजेक्ट बनाने की कोई सीमा नहीं है। आप जितने चाहें उतने प्रोजेक्ट बना सकते हैं, उन्हें विकसित कर सकते हैं और उन्हें विभिन्न सर्वरों पर अपलोड कर सकते हैं।", + "HowManyDevelopers": "एबीपी कमर्शियल पर कितने डेवलपर काम कर सकते हैं?", + "HowManyDevelopersExplanation": "एबीपी वाणिज्यिक लाइसेंस प्रति डेवलपर हैं। विभिन्न लाइसेंस प्रकारों में अलग-अलग डेवलपर सीमाएँ होती हैं। हालाँकि, जब भी आपको आवश्यकता हो, आप किसी भी प्रकार के लाइसेंस में अधिक डेवलपर्स जोड़ सकते हैं। लाइसेंस प्रकार, डेवलपर सीमा और अतिरिक्त डेवलपर लागतों के लिए कीमतें पृष्ठ देखें।", + "ChangingLicenseType": "क्या मैं भविष्य में अपना लाइसेंस प्रकार बदल सकता हूं?", + "ChangingLicenseTypeExplanation": "आप अपने समान लाइसेंस प्रकार में हमेशा नए डेवलपर्स को जोड़ सकते हैं। यह भी देखें \"एबीपी कमर्शियल पर कितने डेवलपर काम कर सकते हैं?\"। आप गणना मूल्य अंतर का भुगतान करके एक उच्च लाइसेंस के लिए भी अपग्रेड कर सकते हैं। जब आप उच्च लाइसेंस योजना में अपग्रेड करते हैं, तो आपको नई योजना का लाभ मिलता है, लेकिन लाइसेंस अपग्रेड लाइसेंस की समाप्ति की तारीख को नहीं बदलता है।", + "LicenseExtendUpgradeDiff": "लाइसेंस विस्तार और उन्नयन के बीच क्या अंतर है?", + "LicenseExtendUpgradeDiffExplanation": " विस्तार: अपने लाइसेंस का विस्तार / नवीनीकरण करके, आप प्रीमियम समर्थन प्राप्त करना और मॉड्यूल और थीम के लिए प्रमुख अपडेट प्राप्त करना जारी रखेंगे। इसके अलावा, आप नई परियोजनाओं को जारी रखने में सक्षम होंगे। और आप अभी भी एबीपी सूट का उपयोग कर पाएंगे जो आपके विकास को गति देता है।


उन्नयन: अपने लाइसेंस को अपग्रेड करके, आप एक उच्च लाइसेंस योजना को बढ़ावा देंगे जिससे आप अतिरिक्त लाभ प्राप्त कर सकेंगे। । लाइसेंस योजनाओं के बीच अंतर की जांच करने के लिए लाइसेंस तुलना तालिका देखें। दूसरी ओर, जब आप अपग्रेड करते हैं, तो आपकी लाइसेंस की समाप्ति तिथि नहीं बदलेगी! > अपनी लाइसेंस की अंतिम तिथि बढ़ाने के लिए, आपको अपने लाइसेंस का विस्तार करना होगा।", + "LicenseRenewalCost": "1 वर्ष के बाद लाइसेंस नवीनीकरण लागत क्या है?", + "LicenseRenewalCostExplanation": "सभी एबीपी वाणिज्यिक स्थायी लाइसेंसों का नवीकरण (विस्तार) दर लाइसेंस सूची मूल्य का {0} है। मानक टीम लाइसेंस का नवीनीकरण मूल्य $ {1} है, मानक व्यवसाय लाइसेंस $ {2} है और मानक एंटरप्राइज़ लाइसेंस $ {3} है। यदि आप पहले से ही ग्राहक हैं, तो उपलब्ध नवीनीकरण मूल्य निर्धारण की समीक्षा करने के लिए अपने खाते में लॉग इन करें ।", + "HowDoIRenewMyLicense": "मैं अपने लाइसेंस का नवीनीकरण कैसे करूँ?", + "HowDoIRenewMyLicenseExplanation": "आप अपने लाइसेंस को संगठन प्रबंधन पृष्ठ पर नेविगेट करके नवीनीकृत कर सकते हैं। हमारी रियायती अर्ली रिन्यूअल दरों का लाभ उठाने के लिए, सुनिश्चित करें कि आप अपने लाइसेंस की समय सीमा समाप्त होने से पहले नवीनीकरण करें। हालाँकि, जब आपका प्रारंभिक नवीनीकरण अवसर बंद हो जाता है, तो यह जानने की चिंता न करें। आपकी सदस्यता समाप्त होने से पहले आपको 2 अनुस्मारक ई-मेल प्राप्त होंगे। हम उन्हें 30 दिन, समाप्ति से 7 दिन पहले भेज देंगे।", + "IsSourceCodeIncluded": "क्या मेरे लाइसेंस में वाणिज्यिक मॉड्यूल और थीम का स्रोत कोड शामिल है?", + "IsSourceCodeIncludedExplanation1": "आपके द्वारा खरीदे गए लाइसेंस प्रकार पर निर्भर करता है:", + "IsSourceCodeIncludedExplanation2": " टीम : आपका समाधान मॉड्यूल और थीम को NuGet और NPM पैकेज के रूप में उपयोग करता है। इसमें उनका स्रोत कोड शामिल नहीं है। इस तरह, जब भी कोई नया संस्करण उपलब्ध हो, आप इन मॉड्यूल और थीम को आसानी से अपग्रेड कर सकते हैं। हालाँकि, आप मॉड्यूल और थीम के स्रोत कोड प्राप्त नहीं कर सकते।", + "IsSourceCodeIncludedExplanation3": " व्यवसाय / उद्यम : टीम लाइसेंस के अतिरिक्त, आप किसी भी मॉड्यूल या थीम की आवश्यकता के स्रोत कोड को डाउनलोड करने में सक्षम हैं। तुम भी एक विशेष मॉड्यूल के लिए NuGet / NPM पैकेज संदर्भ निकाल सकते हैं और इसे पूरी तरह से बदलने के लिए अपने समाधान के लिए अपने स्रोत कोड को सीधे जोड़ सकते हैं।", + "IsSourceCodeIncludedExplanation4": "

एक मॉड्यूल के स्रोत कोड को आपके समाधान में शामिल करना आपको उस मॉड्यूल को अनुकूलित करने की अधिकतम स्वतंत्रता देता है। हालाँकि, तब नया संस्करण जारी होने पर मॉड्यूल को स्वचालित रूप से अपग्रेड करना संभव नहीं होगा।

किसी भी लाइसेंस में ABP सुइट स्रोत कोड शामिल नहीं है, जो एक बाहरी उपकरण है जो आपके लिए कोड बनाता है और सहायता करता है आपके विकास के लिए।

लाइसेंस प्रकारों के अन्य अंतरों के लिए मूल्य निर्धारण पृष्ठ देखें। ", + "ChangingDevelopers": "क्या मैं भविष्य में अपने संगठन के पंजीकृत डेवलपर्स को बदल सकता हूं?", + "ChangingDevelopersExplanation": "अपने लाइसेंस में नए डेवलपर्स को जोड़ने के अलावा, आप मौजूदा डेवलपर्स को भी बदल सकते हैं (आप एक डेवलपर को हटा सकते हैं और एक ही सीट पर एक नया जोड़ सकते हैं) बिना किसी अतिरिक्त लागत के।", + "WhatHappensWhenLicenseEnds": "मेरे लाइसेंस की अवधि समाप्त होने पर क्या होता है?", + "WhatHappensWhenLicenseEndsExplanation1": "ABP कमर्शियल लाइसेंस का प्रकार स्थायी लाइसेंस है। आपके लाइसेंस की समय सीमा समाप्त होने के बाद, आप अपना प्रोजेक्ट विकसित करना जारी रख सकते हैं। और आप अपने लाइसेंस को नवीनीकृत करने के लिए बाध्य नहीं हैं। आपका लाइसेंस एक वर्ष के अपडेट और समर्थन योजना के साथ आता है। नई सुविधाओं को प्राप्त करने के लिए, प्रदर्शन में वृद्धि, बग फिक्स, समर्थन और एबीपी सूट का उपयोग करना जारी रखें, प्रत्येक वर्ष अपनी योजना को नवीनीकृत करना सुनिश्चित करें। जब आपका लाइसेंस समाप्त हो जाता है, तो आप निम्नलिखित लाभ प्राप्त नहीं कर पाएंगे;", + "WhatHappensWhenLicenseEndsExplanation2": "आप एबीपी कमर्शियल का उपयोग करके नए समाधान नहीं बना सकते हैं, लेकिन आप अपने मौजूदा अनुप्रयोगों को हमेशा के लिए विकसित कर सकते हैं।", + "WhatHappensWhenLicenseEndsExplanation3": "आप अपने मुख्य संस्करण के भीतर मॉड्यूल और विषयों के लिए अद्यतन प्राप्त करने में सक्षम होंगे। उदाहरण के लिए; यदि आप किसी मॉड्यूल के v3.2.0 का उपयोग कर रहे हैं, तो आप उस मॉड्यूल के v3.x.x (v3.3.0, v3.5.2 ... आदि) के लिए अपडेट प्राप्त कर सकते हैं। लेकिन आपको अगले प्रमुख संस्करण के लिए अपडेट नहीं मिल सकता है (जैसे v4.x, v5.x)", + "WhatHappensWhenLicenseEndsExplanation4": "आप अपने लाइसेंस समाप्त होने के बाद एबीपी वाणिज्यिक मंच में जोड़े गए नए मॉड्यूल और थीम स्थापित नहीं कर सकते।", + "WhatHappensWhenLicenseEndsExplanation5": "आप एबीपी सूट का उपयोग नहीं कर सकते।", + "WhatHappensWhenLicenseEndsExplanation6": "आपको अब और प्रीमियम सहायता नहीं मिल सकती है।", + "WhatHappensWhenLicenseEndsExplanation7": "यदि आप इन लाभों को प्राप्त करना जारी रखना चाहते हैं तो आप अपनी सदस्यता को नवीनीकृत कर सकते हैं। जब आप अपनी सदस्यता को नवीनीकृत करते हैं तो 20% छूट मिलती है।", + "WhenShouldIRenewMyLicense": "मुझे अपना लाइसेंस कब नवीनीकृत करना चाहिए?", + "WhenShouldIRenewMyLicenseExplanation1": "यदि आप अपना लाइसेंस समाप्त होने के बाद अपने लाइसेंस का नवीनीकरण 1 महीने के भीतर करते हैं, तो कुल लाइसेंस मूल्य पर% 20 छूट लागू होगी।", + "WhenShouldIRenewMyLicenseExplanation2": "यदि आप अपनी लाइसेंस की समाप्ति तिथि से 1 महीने के बाद अपना लाइसेंस नवीनीकृत करते हैं, तो नवीनीकरण मूल्य लाइसेंस खरीद मूल्य के समान होगा और आपके नवीकरण के लिए कोई छूट नहीं होगी।", + "TrialPlan": "क्या आपके पास एक परीक्षण योजना है?", + "TrialPlanExplanation": "अभी के लिए, एबीपी कमर्शियल में ट्रायल प्लान नहीं है। टीम लाइसेंस के लिए हम 30 दिन की मनी बैक गारंटी प्रदान करते हैं। आप पहले 30 दिनों में धनवापसी का अनुरोध कर सकते हैं। बिजनेस और एंटरप्राइज लाइसेंस के लिए, हम 30 दिनों में 60% रिफंड प्रदान करते हैं। ऐसा इसलिए है क्योंकि व्यवसाय और एंटरप्राइज़ लाइसेंस में सभी मॉड्यूल और थीम का पूर्ण स्रोत कोड शामिल है।", + "DoYouAcceptBankWireTransfer": "क्या आप बैंक वायर ट्रांसफर स्वीकार करते हैं?", + "DoYouAcceptBankWireTransferExplanation": "हां, हम बैंक वायर ट्रांसफर स्वीकार करते हैं।
बैंक वायर ट्रांसफर के माध्यम से लाइसेंस राशि भेजने के बाद, हमें अपनी रसीद और अनुरोधित लाइसेंस प्रकार ई-मेल के माध्यम से भेजें।
हमारे अंतरराष्ट्रीय बैंक खाते की जानकारी:", + "HowToUpgrade": "नया संस्करण उपलब्ध होने पर मौजूदा एप्लिकेशन को कैसे अपग्रेड किया जाए?", + "HowToUpgradeExplanation1": "जब आप ABP कमर्शियल का उपयोग करके एक नया एप्लिकेशन बनाते हैं, तो सभी मॉड्यूल और थीम को NuGet और NPM पैकेज के रूप में उपयोग किया जाता है। इसलिए, नया संस्करण उपलब्ध होने पर आप आसानी से संकुल को अपग्रेड कर सकते हैं।", + "HowToUpgradeExplanation2": "मानक NuGet / NPM अपग्रेड के अलावा, ABP CLI एक अपडेट कमांड प्रदान करता है जो आपके समाधान में सभी एबीपी से संबंधित पैकेजों को स्वचालित रूप से ढूंढता है और उन्हें अपग्रेड करता है।", + "DatabaseSupport": "कौन से डेटाबेस सिस्टम समर्थित हैं?", + "DatabaseSupportExplanation": "ABP फ्रेमवर्क स्वयं ही डेटाबेस अज्ञेयवादी है और अपनी प्रकृति के अनुसार किसी भी डेटाबेस प्रदाता के साथ काम कर सकता है। वर्तमान में कार्यान्वित प्रदाताओं की सूची के लिए डेटा एक्सेस दस्तावेज़ देखें।", + "UISupport": "कौन से UI फ्रेमवर्क समर्थित हैं?", + "Supported": "समर्थित", + "UISupportExplanation": "ABP फ्रेमवर्क स्वयं UI फ्रेमवर्क अज्ञेयवादी है और किसी भी UI फ्रेमवर्क के साथ काम कर सकता है। हालाँकि, सभी UI फ्रेमवर्क के लिए स्टार्टअप टेम्प्लेट, मॉड्यूल UI और थीम लागू नहीं किए गए थे। UI विकल्पों की अप-टू-डेट सूची के लिए आरंभ किया गया दस्तावेज़ देखें।", + "MicroserviceSupport": "क्या यह सूक्ष्म सेवा वास्तुकला का समर्थन करता है?", + "MicroserviceSupportExplanation1": "एबीपी ढांचे का एक प्रमुख लक्ष्य सूक्ष्म सेवा समाधान बनाने के लिए एक सुविधाजनक बुनियादी ढांचा प्रदान करना है। यह समझने के लिए कि यह माइक्रो-सर्विस सिस्टम बनाने में कैसे मदद करता है, यह समझने के लिए माइक्रो-सर्विस आर्किटेक्चर दस्तावेज़ देखें।", + "MicroserviceSupportExplanation2": "सभी एबीपी कमर्शियल मॉड्यूल्स को मॉड्यूल डेवलपमेंट बेस्ट प्रैक्टिस दस्तावेज़ का पालन करके माइक्रो-सर्विस परिनियोजन परिदृश्य (अपने एपीआई और डेटाबेस के साथ) का समर्थन करने के लिए डिज़ाइन किया गया है।", + "MicroserviceSupportExplanation3": "हम आपको अपना स्वयं का समाधान बनाने में मदद करने के लिए एक माइक्रो-सेवा वास्तुकला कार्यान्वयन को प्रदर्शित करने वाला एक नमूना माइक्रो-सर्विस डेमो समाधान प्रदान करते हैं।", + "MicroserviceSupportExplanation4": "तो, संक्षिप्त उत्तर \" हां है, यह सूक्ष्म सेवा वास्तुकला का समर्थन करता है \"।", + "MicroserviceSupportExplanation5": "हालाँकि, एक माइक्रो-सर्विस सिस्टम एक समाधान है और हर समाधान में अलग-अलग आवश्यकताएं, नेटवर्क टोपोलॉजी, संचार परिदृश्य, प्रमाणीकरण संभावनाएं, डेटाबेस पृथक्करण / साझा करने के निर्णय, रनटाइम कॉन्फ़िगरेशन, 3 पार्टी सिस्टम एकीकरण और कई और अधिक होंगे।", + "MicroserviceSupportExplanation6": "ABP फ्रेमवर्क और ABP कमर्शियल आपको अपने स्वयं के समाधान का निर्माण करने में मदद करने के लिए सूक्ष्म सेवा परिदृश्य, सूक्ष्म सेवा संगत मॉड्यूल, नमूने और प्रलेखन के लिए बुनियादी ढाँचा प्रदान करता है। लेकिन अपने सपनों के समाधान को सीधे आपके लिए पहले से डाउनलोड करने की उम्मीद न करें। आपको इसे समझने और अपनी आवश्यकताओं के आधार पर कुछ हिस्सों को एक साथ लाने की आवश्यकता होगी।", + "WhereCanIDownloadSourceCode": "मैं स्रोत-कोड कहां से डाउनलोड कर सकता हूं?", + "WhereCanIDownloadSourceCodeExplanation": "आप एबीपी सूट या एबीपी सीएलआई के माध्यम से सभी एबीपी मॉड्यूल, कोणीय पैकेज और थीम के स्रोत कोड डाउनलोड कर सकते हैं। स्रोत-कोड डाउनलोड कैसे करें? देखें", + "ComputerLimitation": "एबीपी विकसित करते समय एक डेवलपर कितने कंप्यूटरों पर लॉगिन कर सकता है?", + "ComputerLimitationExplanation": "हम विशेष रूप से प्रति व्यक्ति / लाइसेंस प्राप्त डेवलपर के लिए {0} कंप्यूटर की अनुमति देते हैं। जब भी किसी तीसरे मशीन पर एबीपी कमर्शियल उत्पादों को विकसित करने के लिए डेवलपर की आवश्यकता होती है, तो स्थिति को समझाते हुए लाइसेंस@abp.io को एक ई-मेल भेजा जाना चाहिए और फिर हम अपने सिस्टम में उचित आवंटन करेंगे।", + "RefundPolicy": "क्या आपके पास धनवापसी नीति है?", + "RefundPolicyExplanation": "आप अपनी लाइसेंस खरीद के 30 दिन के भीतर धनवापसी का अनुरोध कर सकते हैं। व्यवसाय और उद्यम लाइसेंस प्रकार में स्रोत-कोड डाउनलोड विकल्प होता है, इसलिए व्यापार और उद्यम के लिए धनवापसी उपलब्ध नहीं होती है (और कोई भी लाइसेंस जिसमें स्रोत-कोड प्राप्त करने का अधिकार शामिल होता है)। इसके अलावा, नवीनीकरण और दूसरे लाइसेंस खरीद के लिए कोई भी रिफंड नहीं किया जाता है।", + "HowCanIRefundVat": "मैं VAT कैसे वापस कर सकता हूँ?", + "HowCanIRefundVatExplanation1": "यदि आपने 2 चेकआउट का उपयोग करके भुगतान किया है, तो आप अपने 2 चेकआउट खाते के माध्यम से वैट वापस कर सकते हैं:", + "HowCanIRefundVatExplanation2": "अपने 2 चेकआउट खाते में लॉग इन करें", + "HowCanIRefundVatExplanation3": "उपयुक्त आदेश खोजें और \"रिफंड बेल्ड वैट\" दबाएं (अपनी वैट आईडी दर्ज करें)", + "HowCanIGetMyInvoice": "मैं अपना चालान कैसे प्राप्त कर सकता हूं?", + "HowCanIGetMyInvoiceExplanation": "लाइसेंस खरीदने के लिए 2 भुगतान गेटवे हैं: PayU और 2 चेकआउट। यदि आप 2Checkout गेटवे के माध्यम से अपना लाइसेंस खरीदते हैं, तो यह आपके ईमेल पते पर पीडीएफ चालान भेजता है, देखें 2 चेकआउट चालान। यदि आप पेयू गेटवे या बैंक वायर ट्रांसफर के माध्यम से खरीदते हैं, तो हम आपका चालान तैयार करेंगे और भेजेंगे। आप अपने चालान का अनुरोध संगठन प्रबंधन पृष्ठ से कर सकते हैं", + "Forum": "मंच", + "SupportExplanation": "ABP कमर्शियल लाइसेंस एक टीम द्वारा प्रीमियम फ़ोरम सपोर्ट प्रदान करता है जिसमें ABP फ्रेमवर्क विशेषज्ञ होते हैं।", + "PrivateTicket": "निजी टिकट", + "PrivateTicketExplanation": "एंटरप्राइज लाइसेंस में ई-मेल और टिकट प्रणाली के साथ एक निजी सहायता भी शामिल है।", + "AbpSuiteExplanation1": "ABP सुइट आपको कुछ ही मिनटों में वेब पेज बनाने की अनुमति देता है। यह .NET कोर ग्लोबल टूल है जिसे कमांड लाइन से इंस्टॉल किया जा सकता है।", + "AbpSuiteExplanation2": "यह एक नया ABP समाधान बना सकता है, डेटाबेस से फ्रंट-एंड तक CRUD पेज बना सकता है। तकनीकी ओवरव्यू के लिए दस्तावेज़ देखें", + "FastEasy": "तेज और आसान", + "AbpSuiteExplanation3": "ABP सुइट आपको आसानी से CRUD पेज बनाने की अनुमति देता है। आपको बस अपनी इकाई और उसके गुणों को परिभाषित करने की आवश्यकता है, बाकी को आप के लिए एबीपी सूट करने दें! एबीपी सूट कुछ ही सेकंड में आपके सीआरयूडी पृष्ठ के लिए सभी आवश्यक कोड उत्पन्न करता है। यह Angular, MVC और Blazor यूजर इंटरफेस को सपोर्ट करता है।", + "RichOptions": "अमीर विकल्प", + "AbpSuiteExplanation4": "ABP सुइट रेजर पेज और Angular । यह MongoDB जैसे कई डेटाबेस का समर्थन करता है और सभी डेटाबेस EntityFramework Core <द्वारा समर्थित है / strong> (MS SQL सर्वर, Oracle, MySql, PostgreSQL और )।", + "AbpSuiteExplanation5": "अच्छी बात यह है कि, आपको उन विकल्पों के बारे में चिंता करने की ज़रूरत नहीं है। एबीपी सूट आपके प्रोजेक्ट के प्रकार को समझता है और आपकी परियोजना के लिए कोड बनाता है और उत्पन्न कोड को आपके प्रोजेक्ट में सही जगह पर रखता है।", + "SourceCode": "सोर्स कोड", + "AbpSuiteExplanation6": "ABP स्वीट आपके लिए सोर्स कोड जेनरेट करता है! यह वेब पेज जनरेट करने के लिए मैजिक फाइल्स जेनरेट नहीं करता है। एबीपी सूट इकाई, रिपोजिटरी, एप्लीकेशन सर्विस, कोड फर्स्ट माइग्रेशन, जावास्क्रिप्ट / टाइपस्क्रिप्ट और सीएसएचटीएमएल / एचटीएमएल और आवश्यक इंटरफेस के लिए भी स्रोत कोड उत्पन्न करता है। ABP Suite सॉफ्टवेयर डेवलपमेंट के बेस्ट प्रैक्टिसेस के अनुसार कोड भी तैयार करता है, इसलिए आपको जनरेट किए गए कोड की गुणवत्ता के बारे में चिंता करने की आवश्यकता नहीं है।", + "AbpSuiteExplanation7": "चूँकि आपके पास सही एप्लिकेशन लेयर्स में जेनरेट किए गए CRUD पेज के बिल्डिंग ब्लॉक्स का सोर्स कोड है, आप आसानी से सोर्स कोड को संशोधित कर सकते हैं और अपने कस्टम / bussiness लॉजिक को जेनरेट कोड में इंजेक्ट कर सकते हैं।", + "CrossPlatform": "क्रास प्लेटफार्म", + "AbpSuiteExplanation8": "ABP सुइट .NET .NET के साथ बनाया गया है और यह क्रॉस प्लेटफॉर्म है। यह आपके स्थानीय कंप्यूटर पर एक वेब एप्लिकेशन के रूप में चलता है। आप इसे Windows , Mac और Linux पर चला सकते हैं", + "OtherFeatures": "अन्य सुविधाओं", + "OtherFeatures1": "अपडेट्स NuGet और NPM पैकेज आपके समाधान पर आसानी से।", + "OtherFeatures2": "खरोंच से पहले से ही उत्पन्न पृष्ठों को पुन: उत्पन्न करता है।", + "OtherFeatures3": "नए समाधान बनाता है", + "ThanksForCreatingProject": "अपना प्रोजेक्ट बनाने के लिए धन्यवाद!", + "HotToRunSolution": "अपना हल कैसे चलाएं?", + "HotToRunSolutionExplanation": "अपने समाधान को कॉन्फ़िगर करने और चलाने का तरीका जानने के लिए आरंभ किया गया दस्तावेज़ देखें।", + "GettingStarted": "शुरू करना", + "WebAppDevTutorial": "वेब ऐप देव ट्यूटोरियल", + "WebAppDevTutorialExplanation": "कदम विकास नमूना द्वारा एक कदम के लिए वेब अनुप्रयोग विकास ट्यूटोरियल दस्तावेज़ देखें।", + "Document": "डाक्यूमेंट", + "UsingABPSuiteToCURD": "CRUD पेज जनरेशन और टूलिंग के लिए ABP सूट का उपयोग करना", + "SeeABPSuiteDocument": "ABP सुइट का उपयोग जानने के लिए ABP सुइट दस्तावेज़ देखें।", + "AskQuestionsOnSupport": "आप एबीपी कमर्शियल सपोर्ट पर सवाल पूछ सकते हैं।", + "Documentation": "प्रलेखन", + "SeeModulesDocument": "सभी वाणिज्यिक (समर्थक) मॉड्यूल और उनके दस्तावेजों की सूची के लिए मॉड्यूल दस्तावेज़ देखें।", + "Pricing": "मूल्य निर्धारण", + "PricingExplanation": "आज अपनी व्यावसायिक आवश्यकताओं के लिए सुविधाओं और कार्यक्षमता का चयन करें। जैसे ही आपका व्यवसाय बढ़ता है, आसानी से अपग्रेड करें।", + "Team": "टीम", + "Business": "व्यापार", + "Enterprise": "उद्यम", + "Custom": "रिवाज", + "IncludedDeveloperLicenses": "डेवलपर लाइसेंस शामिल हैं", + "CustomLicenceOrAdditionalServices": "कस्टम लाइसेंस या अतिरिक्त सेवाओं की आवश्यकता है?", + "CustomOrVolumeLicense": "कस्टम या वॉल्यूम लाइसेंस", + "LiveTrainingSupport": "लाइव प्रशिक्षण और समर्थन", + "AndMore": "और अधिक", + "AdditionalDeveloperLicense": "अतिरिक्त डेवलपर लाइसेंस", + "ProjectCount": "प्रोजेक्ट की गिनती", + "AllProModules": "सभी प्रो मॉड्यूल", + "AllProThemes": "सभी प्रो थीम", + "AllProStartupTemplates": "सभी प्रो स्टार्टअप टेम्प्लेट", + "SourceCodeOfAllModules": "सभी मॉड्यूल का स्रोत कोड", + "SourceCodeOfAllThemes": "सभी विषयों का स्रोत कोड", + "PerpetualLicense": "हमेशा के लिए लाइसेंस", + "UnlimitedServerDeployment": "असीमित सर्वर की तैनाती", + "YearUpgrade": "1 साल का उन्नयन", + "YearPremiumForumSupport": "1 साल का प्रीमियम फोरम सपोर्ट", + "ForumSupportIncidentCountYear": "फोरम समर्थन घटना गिनती / वर्ष", + "PrivateTicketEmailSupport": "निजी टिकट और ईमेल समर्थन", + "BuyNow": "अभी खरीदें", + "PayViaAmexCard": "मैं अपने AMEX कार्ड के माध्यम से कैसे भुगतान कर सकता हूं?", + "PayViaAmexCardDescription": "डिफ़ॉल्ट भुगतान गेटवे 'Iyzico' सुरक्षा उपायों के कारण कुछ AMEX क्रेडिट कार्डों को अस्वीकार कर सकता है। इस मामले में, आप वैकल्पिक भुगतान गेटवे '2 चेकआउट' के माध्यम से भुगतान कर सकते हैं।", + "ThankYou": "धन्यवाद", + "InvalidReCaptchaErrorMessage": "ReCAPTCHA को सत्यापित करने में एक त्रुटि हुई थी। कृपया पुन: प्रयास करें।" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json new file mode 100644 index 0000000000..766702a92b --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json @@ -0,0 +1,296 @@ +{ + "culture": "it", + "texts": { + "OrganizationManagement": "Gestione dell'organizzazione", + "OrganizationList": "Elenco delle organizzazioni", + "Volo.AbpIo.Commercial:010003": "Non sei il proprietario di questa organizzazione!", + "OrganizationNotFoundMessage": "Nessuna organizzazione trovata!", + "DeveloperCount": "Sviluppatori allocati / totali", + "QuestionCount": "Domande rimanenti / totali", + "Unlimited": "Illimitato", + "Owners": "Proprietari", + "AddMember": "Aggiungi membro", + "AddOwner": "Aggiungi proprietario", + "AddDeveloper": "Aggiungi sviluppatore", + "UserName": "Nome utente", + "Name": "Nome", + "EmailAddress": "Indirizzo e-mail", + "Developers": "Sviluppatori", + "LicenseType": "Tipo di licenza", + "Manage": "Gestire", + "StartDate": "Data d'inizio", + "EndDate": "Data di fine", + "Modules": "Moduli", + "LicenseExtendMessage": "La data di fine della tua licenza è estesa a {0}", + "LicenseUpgradeMessage": "La tua licenza è stata aggiornata a {0}", + "LicenseAddDeveloperMessage": "{0} sviluppatori aggiunti alla tua licenza", + "Volo.AbpIo.Commercial:010004": "Impossibile trovare l'utente specificato! L'utente deve essere già registrato.", + "MyOrganizations": "Le mie organizzazioni", + "ApiKey": "Chiave API", + "UserNameNotFound": "Nessun utente con nome utente {0}", + "SuccessfullyAddedToNewsletter": "Grazie per esserti iscritto alla nostra newsletter!", + "MyProfile": "Il mio profilo", + "EmailNotValid": "Si prega di inserire un indirizzo email valido.", + "JoinOurMarketingNewsletter": "Iscriviti alla nostra newsletter di marketing", + "WouldLikeToReceiveMarketingMaterials": "Vorrei ricevere materiale di marketing come offerte di prodotti e offerte speciali.", + "StartUsingYourLicenseNow": "Inizia subito a usare la tua licenza!", + "WelcomePage": "Pagina di benvenuto", + "UnsubscriptionExpireEmail": "Annulla l'iscrizione alle e-mail di promemoria della data di scadenza della licenza", + "UnsubscribeLicenseExpireEmailReminderMessage": "Questa sottoscrizione e-mail contiene solo il promemoria della data di scadenza della licenza.", + "UnsubscribeFromLicenseExpireEmails": "Se non desideri ricevere le e-mail sulla data di scadenza della licenza, puoi annullare l'iscrizione in qualsiasi momento lo desideri.", + "Unsubscribe": "Annulla l'iscrizione", + "NotOrganizationMember": "Non sei membro di nessuna organizzazione.", + "UnsubscribeLicenseExpirationEmailSuccessTitle": "Iscrizione annullata con successo", + "UnsubscribeLicenseExpirationEmailSuccessMessage": "Non riceverai più email di promemoria della data di scadenza della licenza.", + "IndexPageHeroSection": " Una completa piattaforma di sviluppo web integrata framework ", + "AbpCommercialShortDescription": "ABP Commercial fornisce moduli applicativi predefiniti, strumenti per lo sviluppo rapido di applicazioni, temi dell'interfaccia utente professionale, supporto premium e altro ancora.", + "LiveDemo": "Dimostrazione dal vivo", + "GetLicence": "Ottieni una licenza", + "Application": "Applicazione", + "StartupTemplates": "Modelli di avvio", + "Startup": "Avviare", + "Templates": "Modelli", + "Developer": "Sviluppatore", + "Tools": "Utensili", + "Premium": "Premium", + "PremiumSupport": "Supporto premium", + "PremiumForumSupport": "Supporto forum premium", + "UI": "UI", + "Themes": "Temi", + "JoinOurNewsletter": "Iscriviti alla nostra newsletter", + "Send": "Spedire", + "Learn": "Imparare", + "AdditionalServices": "Servizi aggiuntivi", + "WhatIsABPFramework": "QUAL È IL QUADRO ABP?", + "OpenSourceBaseFramework": "Framework di base open source", + "ABPFrameworkExplanation": "

ABP Commercial si basa su ABP Framework, un framework per applicazioni web open source e guidato dalla comunità per ASP.NET Core.

ABP Framework fornisce un'eccellente infrastruttura per la scrittura gestibile ed estensibile e codice testabile con best practice.

Costruito e integrato in strumenti popolari che già conosci. Bassa curva di apprendimento, facile adattamento, sviluppo confortevole.

", + "Modular": "Modulare", + "MicroserviceCompatible": "Compatibile con microservizi", + "DomainDrivenDesignInfrastructure": "Infrastruttura di progettazione basata sul dominio", + "MultiTenancy": "Multi-Tenancy", + "DistributedMessaging": "Messaggistica distribuita", + "DynamicProxying": "Proxying dinamico", + "BackgroundJobs": "Lavori in background", + "AuditLogging": "Registrazione di audit", + "BLOBStoring": "Archiviazione BLOB", + "BundlingMinification": "Raggruppamento e minimizzazione", + "AdvancedLocalization": "Localizzazione avanzata", + "ManyMore": "Molti altri", + "ExploreTheABPFramework": "Esplora il framework ABP", + "WhyUseTheABPCommercial": "Perché utilizzare lo spot pubblicitario ABP?", + "WhyUseTheABPCommercialExplanation": "

La creazione di applicazioni Web di livello aziendale può essere complessa e richiede tempo.

ABP Commercial offre l'infrastruttura di base perfetta necessaria per tutti i moderni ASP.NET Core di livello aziendale soluzioni basate. Dalla progettazione all'implementazione, l'intero ciclo di sviluppo è potenziato dalle funzionalità e dai moduli integrati di ABP.

", + "StartupTemplatesShortDescription": "I modelli di avvio ti consentono di avviare rapidamente il tuo progetto in pochi secondi.", + "UIFrameworksOptions": "Opzioni dei framework dell'interfaccia utente;", + "DatabaseProviderOptions": "Opzioni del provider di database;", + "PreBuiltApplicationModules": "Moduli applicativi predefiniti", + "PreBuiltApplicationModulesShortDescription": "I requisiti delle applicazioni più comuni sono già stati sviluppati per te come moduli riutilizzabili.", + "Account": "account", + "Blogging": "Blogging", + "Identity": "Identità", + "IdentityServer": "Identity Server", + "Saas": "Saas", + "LanguageManagement": "Gestione della lingua", + "TextTemplateManagement": "Gestione dei modelli di testo", + "See All Modules": "SeeAllModules", + "ABPSuite": "ABP Suite", + "AbpSuiteShortDescription": "ABP Suite è uno strumento complementare all'ABP Commercial.", + "AbpSuiteExplanation": "Ti consente di creare pagine web in pochi minuti. È uno strumento .NET Core Global che può essere installato dalla riga di comando. Può creare una nuova soluzione ABP, generare pagine CRUD dal database al front-end.", + "Details": "Dettagli", + "LeptonTheme": "Tema Lepton", + "ProfessionalModernUIThemes": "Temi dell'interfaccia utente moderni e professionali", + "LeptonThemeExplanation": "Lepton fornisce una gamma di temi di amministrazione Bootstrap che fungono da solida base per qualsiasi progetto che richieda dashboard di amministrazione.", + "DefaultTheme": "Tema predefinito", + "MaterialTheme": "Tema materiale", + "Default2Theme": "Tema predefinito 2", + "DarkTheme": "Tema scuro", + "DarkBlueTheme": "Tema blu scuro", + "LightTheme": "Tema chiaro", + "ProudToWorkWith": "Orgoglioso di lavorare con", + "OurConsumers": "Centinaia di aziende e sviluppatori in oltre 50 paesi in tutto il mondo si affidano a ABP Commercial.", + "JoinOurConsumers": "Unisciti a loro e crea prodotti sorprendenti velocemente.", + "AdditionalServicesExplanation": "Hai bisogno di servizi aggiuntivi o personalizzati? Noi e i nostri partner possiamo fornire; ", + "CustomProjectDevelopment": "Sviluppo di progetti personalizzati", + "CustomProjectDevelopmentExplanation": "Sviluppatori dedicati per i tuoi progetti personalizzati.", + "PortingExistingProjects": "Porting di progetti esistenti", + "PortingExistingProjectsExplanation": "Migrazione dei tuoi progetti legacy alla piattaforma ABP.", + "LiveSupport": "Supporto dal vivo", + "LiveSupportExplanation": "Opzione di supporto remoto dal vivo quando ne hai bisogno.", + "Training": "Formazione", + "TrainingExplanation": "Formazione dedicata per i tuoi sviluppatori.", + "OnBoarding": "Onboarding", + "OnBoardingExplanation": "Aiuta a configurare i tuoi ambienti di sviluppo, CI e CD.", + "PrioritizedTechnicalSupport": "Assistenza tecnica prioritaria", + "PremiumSupportExplanation": "Oltre al grande supporto della comunità del framework ABP, il nostro team di supporto risponde alle domande tecniche e ai problemi degli utenti commerciali con alta priorità.", + "SeeTheSupportOptions": "Vedi le opzioni di supporto", + "Contact": "Contatto", + "TellUsWhatYouNeed": "Dicci di cosa hai bisogno.", + "YourMessage": "Il tuo messaggio", + "YourFullName": "Il tuo nome completo", + "EmailField": "Indirizzo e-mail", + "YourEmailAddress": "Il tuo indirizzo di posta elettronica", + "HowMayWeHelpYou": "Come possiamo aiutarti?", + "SendMessage": "Invia messaggio", + "Success": "Successo", + "WeWillReplyYou": "Abbiamo ricevuto il tuo messaggio e ti contatteremo a breve.", + "GoHome": "Andare a casa", + "CreateLiveDemo": "Crea demo live", + "RegisterToTheNewsletter": "Registrati alla newsletter per ricevere informazioni su ABP.IO, comprese le nuove versioni ecc.", + "EnterYourEmailOrLogin": "Inserisci il tuo indirizzo e-mail per creare la tua demo o
Accedi utilizzando il tuo account esistente.", + "ApplicationTemplate": "Modello di applicazione", + "ApplicationTemplateExplanation": "Il modello di avvio dell'applicazione viene utilizzato per creare una nuova applicazione web.", + "EfCoreProvider": "Entity Framework (supporta SQL Server, MySQL, PostgreSQL, Oracle e altri )", + "AlreadyIncludedInTemplateModules": "I seguenti moduli sono già inclusi e configurati in questo modello:", + "ApplicationTemplateArchitecture": "Questo modello di applicazione supporta anche un'architettura a più livelli in cui il livello dell'interfaccia utente, il livello API e il servizio di autenticazione sono fisicamente separati.", + "SeeTheGuideOrGoToTheLiveDemo": "Consulta la guida per sviluppatori per informazioni tecniche su questo modello o vai alla demo live.", + "DeveloperGuide": "Guida per sviluppatori", + "ModuleTemplate": "Modello di modulo", + "ModuleTemplateExplanation1": "Vuoi creare un modulo e riutilizzarlo in diverse applicazioni? Questo modello di avvio prepara tutto per iniziare a creare un modulo dell'applicazione riutilizzabile o un microservizio .", + "ModuleTemplateExplanation2": "

Puoi supportare uno o più framework UI, uno o più provider di database per un singolo modulo. Il modello di avvio è configurato per eseguire e testare il modulo in un'applicazione minima oltre all'unità e all'infrastruttura di test di integrazione.

Consulta la guida per sviluppatori per informazioni tecniche su questo modello.

", + "WithAllStyleOptions": "con tutte le opzioni di stile", + "Demo": "Demo", + "SeeAllModules": "Vedi tutti i moduli", + "ABPCLIExplanation": "ABP CLI (Command Line Interface) è uno strumento a riga di comando per eseguire alcune operazioni comuni per soluzioni basate su ABP.", + "ABPSuiteEasilyCURD": "ABP Suite è uno strumento che ti permette di creare facilmente pagine CRUD", + "WeAreHereToHelp": "Siamo qui per Aiuto ", + "BrowseOrAskQuestion": "Puoi sfogliare i nostri argomenti della guida o cercare nelle domande frequenti oppure puoi farci una domanda utilizzando il modulo di contatto .", + "SearchQuestionPlaceholder": "Cerca nelle domande frequenti", + "WhatIsTheABPCommercial": "Cos'è l'ABP Commercial?", + "WhatAreDifferencesThanAbpFramework": "Quali sono le differenze tra ABP Framework open source e ABP Commercial?", + "ABPCommercialExplanation": "ABP Commercial è un insieme di moduli, strumenti, temi e servizi premium basati sul framework ABP open source. ABP Commercial è sviluppato e supportato dallo stesso team dietro il framework ABP.", + "WhatAreDifferencesThanABPFrameworkExplanation": "

ABP framework è un framework di sviluppo di applicazioni compatibile con micro-servizi per ASP.NET Core modulare. Fornisce un'architettura completa e una solida infrastruttura per farti concentrare sul tuo codice aziendale piuttosto che ripetere te stesso per ogni nuovo progetto. Si basa sulle migliori pratiche di sviluppo software e su strumenti popolari che già conosci.

Il framework ABP è completamente gratuito, open source e guidato dalla comunità. Fornisce inoltre un tema gratuito e alcuni moduli predefiniti (ad es. Gestione delle identità e gestione dei tenant).

", + "VisitTheFrameworkVSCommercialDocument": "Visita il seguente link, per ulteriori informazioni {1} ", + "ABPCommercialFollowingBenefits": "ABP Commercial aggiunge i seguenti vantaggi al framework ABP;", + "Professional": "Professionale", + "UIThemes": "Temi dell'interfaccia utente", + "EnterpriseModules": " moduli applicativi preconfigurati, ricchi di funzionalità (ad es. Gestione di Identity Server, gestione SaaS, gestione della lingua)", + "ToolingToSupport": "Strumenti per supportare la produttività dello sviluppo (ad es. ABP Suite )", + "PremiumSupportLink": "Supporto Premium premium", + "WhatDoIDownloadABPCommercial": "Cosa devo scaricare quando acquisto ABP Commercial?", + "CreateUnlimitedSolutions": "Dopo aver acquistato una licenza commerciale ABP, sarai in grado di creare soluzioni illimitate come descritto nel documento Guida introduttiva .", + "ABPCommercialSolutionExplanation": "Quando crei una nuova applicazione, ottieni una soluzione Visual Studio (un modello di avvio) in base alle tue preferenze. La soluzione scaricata ha moduli e temi commerciali già installati e configurati per te. Puoi rimuovere un modulo preinstallato o aggiungere un altro modulo, se lo desideri. Tutti i moduli e temi vengono usati come pacchetti NuGet / NPM per impostazione predefinita.", + "StartDevelopWithTutorials": "La soluzione scaricata è ben progettata e documentata. Puoi iniziare a sviluppare il tuo codice aziendale basato su di esso seguendo i tutorial ", + "TryTheCommercialDemo": "Puoi provare la demo per vedere un'applicazione di esempio creata utilizzando il modello di avvio di ABP Commercial.", + "HowManyProducts": "Quanti prodotti / soluzioni differenti posso costruire utilizzando ABP Commercial?", + "HowManyProductsExplanation": "Non ci sono limiti per creare un progetto ABP. Puoi creare tutti i progetti che desideri, svilupparli e caricarli su server diversi.", + "HowManyDevelopers": "Quanti sviluppatori possono lavorare su ABP Commercial?", + "HowManyDevelopersExplanation": "Le licenze commerciali ABP sono per sviluppatore. Diversi tipi di licenza hanno diversi limiti per sviluppatori. Tuttavia, puoi aggiungere più sviluppatori a qualsiasi tipo di licenza ogni volta che ne hai bisogno. Consulta la pagina dei prezzi per i tipi di licenza, i limiti per gli sviluppatori e i costi aggiuntivi per gli sviluppatori.", + "ChangingLicenseType": "Posso cambiare il mio tipo di licenza in futuro?", + "ChangingLicenseTypeExplanation": "Puoi sempre aggiungere nuovi sviluppatori con lo stesso tipo di licenza. Vedi anche \"Quanti sviluppatori possono lavorare su ABP Commercial?\". Puoi anche passare a una licenza superiore pagando la differenza di prezzo calcolata. Quando esegui l'aggiornamento a un piano di licenza superiore, ottieni i vantaggi del nuovo piano, ma l'aggiornamento della licenza non modifica la data di scadenza della licenza.", + "LicenseExtendUpgradeDiff": "Qual è la differenza tra estensione della licenza e aggiornamento?", + "LicenseExtendUpgradeDiffExplanation": " Estensione: estendendo / rinnovando la tua licenza, continuerai a ricevere supporto premium e a ricevere aggiornamenti importanti per moduli e temi. Inoltre, potrai continuare a creare nuovi progetti. E sarai ancora in grado di utilizzare ABP Suite che accelera il tuo sviluppo.
Upgrade: aggiornando la tua licenza, promuoverai un piano di licenza superiore che ti consentirà di ottenere ulteriori vantaggi . Consulta la tabella di confronto delle licenze per verificare le differenze tra i piani di licenza. D'altra parte, quando esegui l'upgrade, la data di scadenza della licenza non cambierà! Per estendere la data di fine della licenza, è necessario estendere la licenza.", + "LicenseRenewalCost": "Qual è il costo del rinnovo della licenza dopo 1 anno?", + "LicenseRenewalCostExplanation": "La tariffa di rinnovo (estensione) di tutte le licenze perpetue ABP Commercial è {0} del prezzo di listino della licenza. Il prezzo di rinnovo della licenza Team standard è $ {1}, la licenza Business standard è $ {2} e la licenza Enterprise standard è $ {3}. Se sei già un cliente, accedi al tuo account per esaminare i prezzi di rinnovo disponibili.", + "HowDoIRenewMyLicense": "Come rinnovo la mia licenza?", + "HowDoIRenewMyLicenseExplanation": "Puoi rinnovare la licenza accedendo alla pagina di gestione dell'organizzazione . Per poter usufruire delle nostre tariffe scontate di rinnovo anticipato, assicurati di rinnovare prima della scadenza della licenza. Tuttavia, non preoccuparti di non sapere quando si chiude la tua opportunità di rinnovo anticipato. Riceverai 2 e-mail di promemoria prima della scadenza dell'abbonamento. Li invieremo a 30 giorni, 7 giorni prima della scadenza.", + "IsSourceCodeIncluded": "La mia licenza include il codice sorgente dei moduli e dei temi commerciali?", + "IsSourceCodeIncludedExplanation1": "Dipende dal tipo di licenza che hai acquistato:", + "IsSourceCodeIncludedExplanation2": " Team : la soluzione utilizza i moduli e i temi come pacchetti NuGet e NPM. Non include il loro codice sorgente. In questo modo, puoi aggiornare facilmente questi moduli e temi ogni volta che è disponibile una nuova versione. Tuttavia, non è possibile ottenere il codice sorgente dei moduli e dei temi.", + "IsSourceCodeIncludedExplanation3": " Business / Enterprise : oltre alla licenza Team, puoi scaricare il codice sorgente di qualsiasi modulo o tema di cui hai bisogno. È anche possibile rimuovere i riferimenti al pacchetto NuGet / NPM per un particolare modulo e aggiungere il relativo codice sorgente direttamente alla soluzione per modificarlo completamente.", + "IsSourceCodeIncludedExplanation4": "

Includere il codice sorgente di un modulo nella tua soluzione ti dà la massima libertà di personalizzare quel modulo. Tuttavia, non sarà possibile aggiornare automaticamente il modulo quando viene rilasciata una nuova versione.

Nessuna delle licenze include il codice sorgente di ABP Suite, che è uno strumento esterno che genera codice per te e assiste al tuo sviluppo.

Vedi la pagina dei prezzi per altre differenze tra i tipi di licenza.

", + "ChangingDevelopers": "Posso cambiare gli sviluppatori registrati della mia organizzazione in futuro?", + "ChangingDevelopersExplanation": "Oltre ad aggiungere nuovi sviluppatori alla tua licenza, puoi anche modificare gli sviluppatori esistenti (puoi rimuovere uno sviluppatore e aggiungerne uno nuovo alla stessa postazione) senza alcun costo aggiuntivo.", + "WhatHappensWhenLicenseEnds": "Cosa succede al termine del periodo di licenza?", + "WhatHappensWhenLicenseEndsExplanation1": "Il tipo di licenza commerciale ABP è licenza perpetua . Dopo la scadenza della licenza, puoi continuare a sviluppare il tuo progetto. E non sei obbligato a rinnovare la tua licenza. La tua licenza viene fornita con un anno di aggiornamenti e piano di supporto pronto all'uso. Per continuare a ricevere nuove funzionalità, miglioramenti delle prestazioni, correzioni di bug, supporto e continuare a utilizzare ABP Suite, assicurati di rinnovare il tuo piano ogni anno. Quando la tua licenza scade, non sarai in grado di ottenere più dei seguenti vantaggi;", + "WhatHappensWhenLicenseEndsExplanation2": "Non è possibile creare nuove soluzioni utilizzando ABP Commercial, ma è possibile continuare a sviluppare le applicazioni esistenti per sempre.", + "WhatHappensWhenLicenseEndsExplanation3": "Sarai in grado di ottenere aggiornamenti per i moduli e i temi nella tua versione MAJOR. Per esempio; se stai usando la v3.2.0 di un modulo, puoi comunque ottenere gli aggiornamenti per la v3.x.x (v3.3.0, v3.5.2 ... ecc.) di quel modulo. Ma non puoi ottenere aggiornamenti per la prossima versione principale (come v4.x, v5.x)", + "WhatHappensWhenLicenseEndsExplanation4": "Non è possibile installare nuovi moduli e temi aggiunti alla piattaforma ABP Commercial al termine della licenza.", + "WhatHappensWhenLicenseEndsExplanation5": "Non è possibile utilizzare ABP Suite.", + "WhatHappensWhenLicenseEndsExplanation6": "Non puoi più ottenere l ' assistenza premium .", + "WhatHappensWhenLicenseEndsExplanation7": "Puoi rinnovare l'abbonamento se desideri continuare a usufruire di questi vantaggi. C'è uno sconto del 20% quando rinnovi l'abbonamento.", + "WhenShouldIRenewMyLicense": "Quando devo rinnovare la mia licenza?", + "WhenShouldIRenewMyLicenseExplanation1": "Se rinnovi la licenza entro 1 mese dalla scadenza della licenza, verrà applicato uno sconto del 20% sul prezzo totale della licenza.", + "WhenShouldIRenewMyLicenseExplanation2": "Se rinnovi la licenza dopo 1 mese dalla data di scadenza della licenza, il prezzo di rinnovo sarà lo stesso del prezzo di acquisto della licenza e non ci saranno sconti per il rinnovo.", + "TrialPlan": "Hai un piano di prova?", + "TrialPlanExplanation": "Per ora, ABP Commercial non ha un piano di prova. Per le licenze Team forniamo una garanzia di rimborso di 30 giorni. Puoi richiedere un rimborso solo nei primi 30 giorni. Per le licenze Business ed Enterprise, forniamo un rimborso del 60% in 30 giorni. Questo perché le licenze Business ed Enterprise includono il codice sorgente completo di tutti i moduli e i temi.", + "DoYouAcceptBankWireTransfer": "Accettate bonifici bancari?", + "DoYouAcceptBankWireTransferExplanation": "Sì, accettiamo bonifico bancario.
Dopo aver inviato l'importo della licenza tramite bonifico bancario, inviaci la ricevuta e il tipo di licenza richiesto tramite e-mail.
Informazioni sul nostro conto bancario internazionale:", + "HowToUpgrade": "Come aggiornare le applicazioni esistenti quando è disponibile una nuova versione?", + "HowToUpgradeExplanation1": "Quando crei una nuova applicazione utilizzando ABP Commercial, tutti i moduli e il tema vengono utilizzati come pacchetti NuGet e NPM. Quindi, puoi facilmente aggiornare i pacchetti quando è disponibile una nuova versione.", + "HowToUpgradeExplanation2": "Oltre agli aggiornamenti NuGet / NPM standard, ABP CLI fornisce un comando di aggiornamento che trova e aggiorna automaticamente tutti i pacchetti relativi a ABP nella soluzione.", + "DatabaseSupport": "Quali sistemi di database sono supportati?", + "DatabaseSupportExplanation": "Lo stesso ABP Framework è indipendente dal database e può funzionare con qualsiasi provider di database per sua natura. Consulta il documento di accesso ai dati per un elenco dei fornitori attualmente implementati.", + "UISupport": "Quali framework dell'interfaccia utente sono supportati?", + "Supported": "Supportato", + "UISupportExplanation": "Lo stesso ABP Framework è indipendente dal framework dell'interfaccia utente e può funzionare con qualsiasi framework dell'interfaccia utente. Tuttavia, i modelli di avvio, le interfacce utente dei moduli e i temi non sono stati implementati per tutti i framework dell'interfaccia utente. Consulta il documento introduttivo per l'elenco aggiornato delle opzioni dell'interfaccia utente.", + "MicroserviceSupport": "Supporta l'architettura dei micro-servizi?", + "MicroserviceSupportExplanation1": "Uno degli obiettivi principali del framework ABP è fornire un'infrastruttura conveniente per creare soluzioni di micro-servizi. Consulta il documento sull ' architettura dei micro-servizi per capire come aiuta a creare sistemi di micro-servizi.", + "MicroserviceSupportExplanation2": "Tutti i moduli ABP Commercial sono progettati per supportare scenari di distribuzione di micro-servizi (con la propria API e database) seguendo il documento best practice per lo sviluppo di moduli .", + "MicroserviceSupportExplanation3": "Forniamo una soluzione demo di micro-servizi di esempio che dimostra l'implementazione di un'architettura di micro-servizi per aiutarti a creare la tua soluzione.", + "MicroserviceSupportExplanation4": "Quindi, la risposta breve è \" sì, supporta l'architettura di micro-servizi \".", + "MicroserviceSupportExplanation5": "Tuttavia, un sistema di micro-servizi è una soluzione e ogni soluzione avrà requisiti diversi, topologia di rete, scenari di comunicazione, possibilità di autenticazione, decisioni di separazione / condivisione del database, configurazioni di runtime, integrazioni di sistemi di terze parti e molto altro.", + "MicroserviceSupportExplanation6": "L'ABP Framework e l'ABP Commercial forniscono un'infrastruttura per scenari di micro-servizi, moduli compatibili con micro-servizi, esempi e documentazione per aiutarti a creare la tua soluzione. Ma non aspettarti di scaricare direttamente la soluzione dei tuoi sogni precostruita per te. Dovrai capirlo e riunire alcune parti in base alle tue esigenze.", + "WhereCanIDownloadSourceCode": "Dove posso scaricare il codice sorgente?", + "WhereCanIDownloadSourceCodeExplanation": "È possibile scaricare il codice sorgente di tutti i moduli ABP, pacchetti e temi Angular tramite ABP Suite o ABP CLI. Vedi Come scaricare il codice sorgente? ", + "ComputerLimitation": "Quanti computer può accedere uno sviluppatore durante lo sviluppo di ABP?", + "ComputerLimitationExplanation": "Autorizziamo specificamente {0} computer per singolo sviluppatore / con licenza. Ogni volta che è necessario che uno sviluppatore sviluppi prodotti ABP Commercial su una terza macchina, deve essere inviata un'e-mail a license@abp.io spiegando la situazione e quindi effettueremo l'allocazione appropriata nel nostro sistema.", + "RefundPolicy": "Hai una politica di rimborso?", + "RefundPolicyExplanation": "Puoi richiedere un rimborso entro 30 giorni dall'acquisto della licenza. I tipi di licenza Business ed Enterprise hanno l'opzione di download del codice sorgente, pertanto i rimborsi non sono disponibili per Business ed Enterprise (e qualsiasi licenza che includa il diritto di ricevere il codice sorgente). Inoltre, non vengono effettuati rimborsi per rinnovi e acquisti di seconde licenze.", + "HowCanIRefundVat": "Come posso rimborsare l'IVA?", + "HowCanIRefundVatExplanation1": "Se hai effettuato il pagamento utilizzando 2Checkout, puoi rimborsare l'IVA tramite il tuo account 2Checkout:", + "HowCanIRefundVatExplanation2": "Accedi al tuo account 2Checkout ", + "HowCanIRefundVatExplanation3": "Trova l'ordine appropriato e premi \"Rimborsa IVA tardiva\" (inserisci il tuo numero di partita IVA)", + "HowCanIGetMyInvoice": "Come posso ricevere la mia fattura?", + "HowCanIGetMyInvoiceExplanation": "Esistono 2 gateway di pagamento per l'acquisto di una licenza: PayU e 2Checkout. Se acquisti la tua licenza tramite il gateway 2Checkout, invia la fattura in PDF al tuo indirizzo e-mail, vedi Fatturazione 2Checkout. Se acquisti tramite il gateway PayU o tramite bonifico bancario, prepareremo e invieremo la tua fattura. Puoi richiedere la fattura dalla pagina di gestione dell'organizzazione. ", + "Forum": "Forum", + "SupportExplanation": "Le licenze commerciali di ABP forniscono un supporto forum premium da parte di un team composto dagli esperti di ABP Framework.", + "PrivateTicket": "Biglietto privato", + "PrivateTicketExplanation": "Enterprise License include anche un supporto privato con e-mail e sistema di ticket.", + "AbpSuiteExplanation1": "ABP Suite ti consente di creare pagine web in pochi minuti. È uno strumento .NET Core Global che può essere installato dalla riga di comando.", + "AbpSuiteExplanation2": "Può creare una nuova soluzione ABP, generare pagine CRUD dal database al front-end. Per una panoramica tecnica, vedere il documento ", + "FastEasy": "Veloce e facile", + "AbpSuiteExplanation3": "ABP Suite ti consente di creare facilmente pagine CRUD. Devi solo definire la tua entità e le sue proprietà, lascia che il resto sia ABP Suite per te! ABP Suite genera tutto il codice necessario per la tua pagina CRUD in pochi secondi. Supporta le interfacce utente Angular, MVC e Blazor.", + "RichOptions": "Opzioni ricche", + "AbpSuiteExplanation4": "ABP Suite supporta più opzioni dell'interfaccia utente come Razor Pages e Angular . Supporta anche più database come MongoDB e tutti i database supportati da EntityFramework Core < / strong> (MS SQL Server, Oracle, MySql, PostgreSQL e altro ).", + "AbpSuiteExplanation5": "La cosa buona è che non devi preoccuparti di quelle opzioni. ABP Suite comprende il tipo di progetto e genera il codice per il progetto e inserisce il codice generato nella posizione corretta nel progetto.", + "SourceCode": "Codice sorgente", + "AbpSuiteExplanation6": "ABP Suite genera il codice sorgente per te! Non genera file magici per generare la pagina web. ABP Suite genera il codice sorgente per Entity, Repository, Application Service, Code First Migration, JavaScript / TypeScript e CSHTML / HTML e anche le interfacce necessarie. ABP Suite genera anche il codice in base alle Best Practices di sviluppo software, quindi non devi preoccuparti della qualità del codice generato.", + "AbpSuiteExplanation7": "Dal momento che hai il codice sorgente dei blocchi costitutivi della pagina CRUD generata nei livelli di applicazione corretti, puoi facilmente modificare il codice sorgente e inserire la tua logica personalizzata / aziendale nel codice generato.", + "CrossPlatform": "Piattaforma multipla", + "AbpSuiteExplanation8": "ABP Suite è costruito con .NET Core ed è multipiattaforma. Funziona come un'applicazione web sul tuo computer locale. Puoi eseguirlo su Windows , Mac e Linux ", + "OtherFeatures": "Altre caratteristiche", + "OtherFeatures1": "Aggiorna facilmente i pacchetti NuGet e NPM sulla tua soluzione.", + "OtherFeatures2": "Rigenera le pagine già generate da zero.", + "OtherFeatures3": "Crea nuove soluzioni", + "ThanksForCreatingProject": "Grazie per aver creato il tuo progetto!", + "HotToRunSolution": "Come eseguire la tua soluzione?", + "HotToRunSolutionExplanation": "Vedere il documento introduttivo per apprendere come configurare ed eseguire la soluzione.", + "GettingStarted": "Iniziare", + "WebAppDevTutorial": "Tutorial per sviluppatori di app Web", + "WebAppDevTutorialExplanation": "Vedere il documento tutorial sullo sviluppo di applicazioni Web per un esempio di sviluppo passo passo.", + "Document": "Documento", + "UsingABPSuiteToCURD": "Utilizzo di ABP Suite per la generazione di pagine CRUD e gli strumenti", + "SeeABPSuiteDocument": "Vedere il documento ABP Suite per apprendere l'utilizzo di ABP Suite.", + "AskQuestionsOnSupport": "Puoi porre domande sul supporto commerciale ABP.", + "Documentation": "Documentazione", + "SeeModulesDocument": "Vedere il documento dei moduli per un elenco di tutti i moduli commerciali (pro) e dei relativi documenti.", + "Pricing": "Prezzi", + "PricingExplanation": "Scegli le caratteristiche e le funzionalità di cui la tua azienda ha bisogno oggi. Esegui facilmente l'upgrade man mano che la tua attività cresce.", + "Team": "Squadra", + "Business": "Attività commerciale", + "Enterprise": "Enterprise", + "Custom": "Personalizzato", + "IncludedDeveloperLicenses": "Licenze per sviluppatori incluse", + "CustomLicenceOrAdditionalServices": "Hai bisogno di una licenza personalizzata o di servizi aggiuntivi?", + "CustomOrVolumeLicense": "Licenza personalizzata o multilicenza", + "LiveTrainingSupport": "Formazione e supporto dal vivo", + "AndMore": "e altro ancora", + "AdditionalDeveloperLicense": "Licenza aggiuntiva per sviluppatori", + "ProjectCount": "Conteggio del progetto", + "AllProModules": "Tutti i moduli professionali", + "AllProThemes": "Tutti i temi professionali", + "AllProStartupTemplates": "Tutti i modelli di avvio professionali", + "SourceCodeOfAllModules": "Codice sorgente di tutti i moduli", + "SourceCodeOfAllThemes": "Codice sorgente di tutti i temi", + "PerpetualLicense": "Licenza perpetua", + "UnlimitedServerDeployment": "Distribuzione illimitata del server", + "YearUpgrade": "1 anno di aggiornamento", + "YearPremiumForumSupport": "1 anno di supporto forum premium", + "ForumSupportIncidentCountYear": "Conteggio degli incidenti di supporto del forum / anno", + "PrivateTicketEmailSupport": "Ticket privato e supporto via e-mail", + "BuyNow": "Acquista ora", + "PayViaAmexCard": "Come posso pagare tramite la mia carta AMEX?", + "PayViaAmexCardDescription": "Il gateway di pagamento predefinito \"Iyzico\" potrebbe rifiutare alcune carte di credito AMEX a causa delle misure di sicurezza. In questo caso, puoi pagare tramite il gateway di pagamento alternativo \"2Checkout\".", + "ThankYou": "Grazie", + "InvalidReCaptchaErrorMessage": "Si è verificato un errore durante la verifica di reCAPTCHA. Per favore riprova." + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json index e49c82c6fd..53781de97e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json @@ -31,6 +31,34 @@ "SuccessfullyAddedToNewsletter": "Bültenimize abone olduğunuz için teşekkürler!", "MyProfile": "Profilim", "EmailNotValid": "Lütfen uygun bir e-posta adresi giriniz", - "InvalidReCaptchaErrorMessage": "ReCAPTCHA doğrulanırken hata oluştu, lütfen tekrar deneyin." + "InvalidReCaptchaErrorMessage": "ReCAPTCHA doğrulanırken hata oluştu, lütfen tekrar deneyin.", + "CompanyName": "Şirket", + "YourCompanyName": "Şirketiniz", + "FirstName": "Ad", + "LastName": "Soyad", + "Optional": "Opsiyonel", + "YourFirstName": "Adınız", + "YourLastName": "Soyadınız", + "SpecialOffer": "Özel Teklif", + "SpecialOfferMessage": "Acele et! Fiyatlar sınırlı bir süre için geçerlidir.", + "DiscountRequest": "İndirim İsteği", + "DiscountRequestDescribeCustomerQuestion": "Aşağıdakilerden hangisi sizi tanımlar?", + "DiscountRequestStudentEmailMessage": "E-posta Adresi \".edu\" içermelidir.", + "DiscountRequestDeveloperCount": "Kaç geliştiriciye sahipsiniz?", + "DiscountRequestDeveloperCountExceedMessage": "{0}'ten fazla geliştiricisi olan şirketler için indirimli lisans sağlamıyoruz.", + "DiscountRequestOrganizationName": "Şirket/organizasyon/okul adı", + "Website": "İnternet sitesi", + "GithubUsername": "GitHub kullanıcı adı", + "PhoneNumber": "Telefon numarası", + "Country": "Ülke", + "DescribeABPCommercialUsage": "ABP Commercial kullanarak geliştirmeyi planladığınız projeyi tanımlayın", + "DiscountRequestCertifyInformationMessage": "Tüm bilgilerin gerçek ve doğru olduğunu onaylıyorum.", + "DiscountRequestReceived": "İndirim talebinizi aldık.", + "DiscountRequestStatusMessage": "Verdiğiniz bilgileri kontrol ettikten sonra size cevap vereceğiz.", + "MVCOrRazorPages": "MVC (Razor Pages)", + "Angular": "Angular", + "Blazor": "Blazor", + "New": "Yeni", + "MongoDB": "MongoDB" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json index e92e55bf6c..5f99be6ba8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json @@ -143,7 +143,7 @@ "ApplicationTemplateArchitecture": "应用程序模板还支持UI,API,身份验证服务器物理分离的分层架构.", "SeeTheGuideOrGoToTheLiveDemo": "查看开发人员指南或者查看在线演示了解更多关于模板的信息.", "DeveloperGuide": "开发人员指南", - "ModuleTemplate": "模块模块", + "ModuleTemplate": "模块模板", "ModuleTemplateExplanation1": "你是否想要创建可在不同应用程序之间重用的模块? 这个启动模板准备好了一切来创建可重用的应用程序模块微服务.", "ModuleTemplateExplanation2": "

你可以为一个模块支持单个或多个UI框架, 单个或多个数据库提供程序. 除了单元测试和集成测试基础架构外,启动模板被配置为在一个最小的应用程序中运行和测试你的模块.

查看开发人员指南了解有关此模板的技术信息.

", "WithAllStyleOptions": "使用所有的样式选项", @@ -288,8 +288,36 @@ "ForumSupportIncidentCountYear": "论坛支持事件数量/年", "PrivateTicketEmailSupport": "私有票和email支持", "BuyNow": "现在购买", - "PayViaAmexCard": "我如何通过我的AMEX卡付款?", - "PayViaAmexCardDescription": "由于安全措施,默认付款网关“ Iyzico”可能会拒绝某些AMEX信用卡。 在这种情况下,您可以通过备用付款网关“ 2Checkout”付款。", - "InvalidReCaptchaErrorMessage": "验证reCAPTCHA时出错,请重试。" + "PayViaAmexCard": "我如何通过我的AMEX卡付款?", + "PayViaAmexCardDescription": "由于安全措施,默认付款网关'Iyzico'可能会拒绝某些AMEX信用卡. 在这种情况下, 完全可以通过备用付款网关'2Checkout'付款.", + "InvalidReCaptchaErrorMessage": "验证reCAPTCHA时出错,请重试.", + "CompanyName": "公司名称", + "YourCompanyName": "你的公司名称", + "FirstName": "名", + "LastName": "姓", + "Optional": "可选的", + "YourFirstName": "你的名字", + "YourLastName": "你的姓氏", + "SpecialOffer": "特别优惠", + "SpecialOfferMessage": "尽快付款,价格在一定时间内有效.", + "DiscountRequest": "折扣申请", + "DiscountRequestDescribeCustomerQuestion": "以下哪个选项描述了你?", + "DiscountRequestStudentEmailMessage": "Email地址必须包含'edu'.", + "DiscountRequestDeveloperCount": "你有多少开发人员?", + "DiscountRequestDeveloperCountExceedMessage": "对于超过 {0} 开发人员的公司,我们不提供折扣.", + "DiscountRequestOrganizationName": "公司/组织/学校名称", + "Website": "网站", + "GithubUsername": "GitHub用户名", + "PhoneNumber": "手机号", + "Country": "国家", + "DescribeABPCommercialUsage": "描述你基于ABP商业版进行开发的项目", + "DiscountRequestCertifyInformationMessage": "我证明所有的信息都是真实的.", + "DiscountRequestReceived": "我们收到了你的折扣请求.", + "DiscountRequestStatusMessage": "我们会检查你提供的信息并且给你答复.", + "MVCOrRazorPages": "MVC (Razor Pages)", + "Angular": "Angular", + "Blazor": "Blazor", + "New": "新的", + "MongoDB": "MongoDB" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json index e39eaba846..a676aa9124 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json @@ -25,6 +25,298 @@ "Volo.AbpIo.Commercial:010004": "不能找到指定的使用者! 使用者必須已經註冊.", "MyOrganizations": "我的組織", "ApiKey": "API key", - "UserNameNotFound": "沒有使用者名稱為{0}的使用者" + "UserNameNotFound": "沒有使用者名稱為{0}的使用者", + "SuccessfullyAddedToNewsletter": "感謝你訂閱我們的新聞簡訊!", + "MyProfile": "我的資料", + "EmailNotValid": "請輸入有效的電子郵件地址", + "JoinOurMarketingNewsletter": "加入我們的營銷簡訊", + "WouldLikeToReceiveMarketingMaterials": "我想收到市場營銷資料,例如產品交易和特別優惠.", + "StartUsingYourLicenseNow": "立即開始使用你的許可", + "WelcomePage": "歡迎頁面", + "UnsubscriptionExpireEmail": "退訂許可到期提醒郵件", + "UnsubscribeLicenseExpireEmailReminderMessage": "此電子郵件訂閱僅提醒你許可的到期日期.", + "UnsubscribeFromLicenseExpireEmails": "如果你不想收到關於許可到期郵件,你可以在任何時間取消訂閱.", + "Unsubscribe": "取消訂閱", + "NotOrganizationMember": "你不是任何組織的成員.", + "UnsubscribeLicenseExpirationEmailSuccessTitle": "退訂成功", + "UnsubscribeLicenseExpirationEmailSuccessMessage": "你不會再收到任何許可到期提醒郵件.", + "IndexPageHeroSection": "一個完整的web開發平臺基於 框架", + "AbpCommercialShortDescription": "ABP商業版提供了預構建的應用程序模塊, 快速的應用程序開發工具, 專業的UI主題, 高級支持等.", + "LiveDemo": "在線演示", + "GetLicence" :"獲得許可", + "Application": "應用程序", + "StartupTemplates": "啟動模板", + "Startup": "啟動", + "Templates": "模板", + "Developer": "開發人員", + "Tools": "工具", + "Premium": "高級", + "PremiumSupport": "高級支持", + "PremiumForumSupport": "高級論壇支持", + "UI": "UI", + "Themes": "主題", + "JoinOurNewsletter": "加入我們的時事通訊", + "Send": "發送", + "Learn": "學習", + "AdditionalServices": "額外的服務", + "WhatIsABPFramework": "什麽是ABP框架?", + "OpenSourceBaseFramework": "開源的框架", + "ABPFrameworkExplanation": "

ABP商業版基於ABP框架, 這是一個開源和社區驅動的ASP.NET Core web應用程序開發框架.

ABP框架提供了出色的基礎設施, 使用最佳實踐編寫可維護,可擴展,可測試的代碼.

基於你已經知道的流行工具. 低學習曲線,容易適應,舒適的開發體檢.

", + "Modular": "模塊化", + "MicroserviceCompatible": "微服務兼容", + "DomainDrivenDesignInfrastructure": "領域驅動設計基礎設施", + "MultiTenancy": "多租戶", + "DistributedMessaging": "分布式消息", + "DynamicProxying": "動態代理", + "BackgroundJobs": "後臺作業", + "AuditLogging": "審計日誌", + "BLOBStoring": "BLOB存儲", + "BundlingMinification": "捆綁 & 壓縮", + "AdvancedLocalization": "高級本地化", + "ManyMore": "以及更多", + "ExploreTheABPFramework": "探索ABP框架", + "WhyUseTheABPCommercial": "為什麽使用ABP商業版?", + "WhyUseTheABPCommercialExplanation": "

構建企業級的web應用程序可能復雜和耗時.

ABP商業版提供所有現代企業級基於ASP.NET Core的解決方案所需要的基礎設施. 從設計到部署,整個開發生命周期都由ABP的內置功能和模塊提供支持.

", + "StartupTemplatesShortDescription": "啟動模板使你在幾秒內快速啟動項目.", + "UIFrameworksOptions": "UI框架選項;", + "DatabaseProviderOptions": "數據庫提供程序選項;", + "PreBuiltApplicationModules": "預構建的應用程序模塊", + "PreBuiltApplicationModulesShortDescription": "大多數常見的應用程序需求已經做為可重用的模塊為你開發了.", + "Account": "賬戶", + "Blogging": "博客", + "Identity": "Identity", + "IdentityServer": "Identity Server", + "Saas": "Saas", + "LanguageManagement": "語言管理", + "TextTemplateManagement": "文本模板管理", + "See All Modules": "查看所有的模塊", + "ABPSuite": "ABP Suite", + "AbpSuiteShortDescription": "ABP Suite是ABP商業版的輔助工具.", + "AbpSuiteExplanation": "它讓你在幾分鐘內構建web頁面. 它是一個.Net Core全局工具,可以使用命令行安裝. 它可以創建一個新的ABP解決方案,從數據庫生成前端CURD頁面.", + "Details": "詳情", + "LeptonTheme": "Lepton主題", + "ProfessionalModernUIThemes": "專業, 現代化的UI主題", + "LeptonThemeExplanation": "Lepton提供了一系列的Bootstrap管理主題,為任何需要管理儀表盤的項目提供了堅實的基礎.", + "DefaultTheme": "默認主題", + "MaterialTheme": "Material主題", + "Default2Theme": "默认主題2", + "DarkTheme": "深色主題", + "DarkBlueTheme": "深藍主題", + "LightTheme": "淺色主題", + "ProudToWorkWith": "榮幸與你合作", + "OurConsumers": "全球50多個國家的數百家企業和開發商使用ABP商業版.", + "JoinOurConsumers": "加它他們並快速構建令人驚嘆的產品.", + "AdditionalServicesExplanation": "你是否需要額外或自定義的服務? 我們和我們的合作夥伴可以提供;", + "CustomProjectDevelopment": "自定義項目開發", + "CustomProjectDevelopmentExplanation": "專為你的自定義的開發人員.", + "PortingExistingProjects": "移植現有項目", + "PortingExistingProjectsExplanation": "將你的遷移傳統項目遷移到ABP平臺.", + "LiveSupport": "實時支持", + "LiveSupportExplanation": "在你需要時,可以實時提供遠程支持選項.", + "Training": "培訓", + "TrainingExplanation": "為你的開發人員提供專門培訓.", + "OnBoarding": "管理", + "OnBoardingExplanation": "幫助設置你的開發,CI和CD環境.", + "PrioritizedTechnicalSupport": "優先的技術支持", + "PremiumSupportExplanation": "除了社區對ABP框架出色支持外,我們的支持團隊會優先回答商業用戶的技術問題.", + "SeeTheSupportOptions": "查看支持選項", + "Contact": "聯系", + "TellUsWhatYouNeed": "告訴我們你需要什麽.", + "YourMessage": "你的消息", + "YourFullName": "你的全名", + "EmailField": "E-mail地址", + "YourEmailAddress": "你的e-mail地址", + "HowMayWeHelpYou": "我們如何幫助你", + "SendMessage": "發送消息", + "Success": "成功", + "WeWillReplyYou": "你的消息已經發送! 我們會在短時間內給你答復.", + "GoHome": "回到主頁面", + "CreateLiveDemo": "創建在線演示", + "RegisterToTheNewsletter": "註冊到時事簡報以獲取有關ABP.IO的消息,比如新發布的內容.", + "EnterYourEmailOrLogin": "輸入你的e-mail地址來創建你的演示或者使用你的已有賬號登錄.", + "ApplicationTemplate": "應用程序模板", + "ApplicationTemplateExplanation": "應用程序啟動模板用於創建新的web應用程序.", + "EfCoreProvider": "Entity Framework (支持 SQL Server, MySQL, PostgreSQL, Oracle 和其它)", + "AlreadyIncludedInTemplateModules": "以下模塊已經包含並配置在此模板中:", + "ApplicationTemplateArchitecture": "應用程序模板還支持UI,API,身份驗證服務器物理分離的分層架構.", + "SeeTheGuideOrGoToTheLiveDemo": "查看開發人員指南或者查看在線演示了解更多關於模板的信息.", + "DeveloperGuide": "開發人員指南", + "ModuleTemplate": "模块模板", + "ModuleTemplateExplanation1": "你是否想要創建可在不同應用程序之間重用的模塊? 這個啟動模板準備好了一切來創建可重用的應用程序模塊微服務.", + "ModuleTemplateExplanation2": "

你可以為一個模塊支持單個或多個UI框架, 單個或多個數據庫提供程序. 除了單元測試和集成測試基礎架構外,啟動模板被配置為在一個最小的應用程序中運行和測試你的模塊.

查看開發人員指南了解有關此模板的技術信息.

", + "WithAllStyleOptions": "使用所有的樣式選項", + "Demo": "演示", + "SeeAllModules": "查看所有的模塊", + "ABPCLIExplanation": "ABP CLI(命令行頁面)是一個執行基於ABP解決方案的一些常見操作的命令行工具.", + "ABPSuiteEasilyCURD": "ABP Suite是一個使你輕松創建CURD頁面的工具", + "WeAreHereToHelp": "我們在這裏為你提供幫助", + "BrowseOrAskQuestion": "你可以瀏覽我們的幫助主題或搜索常見的問題, 或者你可以使用聯系表單向我們提問.", + "SearchQuestionPlaceholder": "搜索常見的問題", + "WhatIsTheABPCommercial": "什麽是ABP商業版?", + "WhatAreDifferencesThanAbpFramework": "ABP框架與ABP商業版有什麽不同?", + "ABPCommercialExplanation": "ABP商業版是一套基於開源ABP框架之上的高級模塊,工具,主題和服務. ABP商業版由ABP框架背後的同一團隊開發和支持.", + "WhatAreDifferencesThanABPFrameworkExplanation": "

ABP框架是模塊化,主題化,微服務兼容的ASP.NET Core應用程序開發框架. 它提供了一個完整的架構和強大的基礎設施,讓你專註於自己的業務代碼而不是重復自己的每一個項目. 它基於軟件開發的最佳實踐和你已經知道的流行工具

ABP框架是完全免費,開源和由社區驅動的. 它還提供了一個免費的主題和一些預構建的模塊 (如 identity管理和租戶管理).

", + "VisitTheFrameworkVSCommercialDocument": "訪問以下鏈接,了解更多信息 {1} ", + "ABPCommercialFollowingBenefits": "ABP商業版在ABP框架之上添加了以下好處;", + "Professional": "專業的", + "UIThemes": "UI主題", + "EnterpriseModules": "企業就緒,功能豐富,預構建的應用程序模塊 (如 Identity Server管理, SaaS管理, 語言管理)", + "ToolingToSupport": "支持你的生產力的工具(如. ABP Suite)", + "PremiumSupportLink": "高級支持", + "WhatDoIDownloadABPCommercial": "購買ABP商業版後我可以下載什麽?", + "CreateUnlimitedSolutions": "一旦你購買了ABP商業許可, 你可以創建入門文檔中描述的無限的解決方案.", + "ABPCommercialSolutionExplanation": "創建新應用程序時,將根據你的首選項獲得Visual Studio解決方案(啟動模板). 下載的解決方案已為你安裝並配置了商業模塊和主題. 你可以刪除預裝的模塊,也可以根據需要添加其他模塊. 默認情況下所有模塊和主題都使用NuGet/NPM軟件包.", + "StartDevelopWithTutorials": "下載的解決方案經過精心設計和記錄, 你可以根據教程來開發自己的業務代碼.", + "TryTheCommercialDemo": "你可以嘗試示例來查看使用ABP商業模板創建的示例應用程序.", + "HowManyProducts": "使用ABP商業版,我可以構建多少不同的產品/解決方案?", + "HowManyProductsExplanation": "創建ABP項目沒有限制. 你可以根據需要創建任意數量的項目,進行開發並將其部署到其他服務器.", + "HowManyDevelopers": "有多少開發者可以參與ABP商業版工作?", + "HowManyDevelopersExplanation": "ABP商業許可是針對每個開發人員的. 不同的許可類型具有不同的開發人員限制. 但是你可以在需要時將更多開發人員添加到任何許可類型. 查看許可類型,開發人員限制和額外的開發人員成本的價格頁面.", + "ChangingLicenseType": "將來更改我的許可類型嗎?", + "ChangingLicenseTypeExplanation": "你始終可以在同一許可中添加新的開發人員. 參閱 \"有多少開發者可以參與ABP商業版工作?\". 你還可以通過支付計算出的價格差來升級到更高的許可. 當你升級到更高的許可計劃時,可以享受新計劃的好處,但是許可升級不會更改許可的到期日期.", + "LicenseExtendUpgradeDiff": "許可擴展和升級有什麽區別?", + "LicenseExtendUpgradeDiffExplanation": "擴展: 通過擴展/更新許可,你將繼續獲得高級支持,並獲得有關模塊和主題的重大更新. 此外你將能夠繼續創建新項目. 而且你仍然可以使用ABP Suite來加快開發速度.
升級: 通過升級許可,你將升級到更高的許可計劃,這將使你獲得更多好處. 查看 許可比較表來檢查許可計劃之間的差異. 另一方面,當你升級時你的許可到期日期不會改變!要延長你的許可終止日期,你需要延長你的許可.", + "LicenseRenewalCost": "一年後的許可續期費用是多少?", + "LicenseRenewalCostExplanation": "ABP商業版的續費價格均為原價的{0}. Team版本的續費價格是${1}, Business版本的續訂價格是${2}, Enterprise版本的續訂價格是${3}. 如果你已經購買了, 請登錄帳戶以查看續訂價格.", + "HowDoIRenewMyLicense": "如何續費我的許可證?", + "HowDoIRenewMyLicenseExplanation": "你可以登錄以進行續費. 為了享受我們的續費折扣, 請確保在許可證到期之前進行續費, 我們會在到期前7天和30天發送2封續費提醒郵件.", + "IsSourceCodeIncluded": "我的許可是否包括商業模塊和主題的源代碼?", + "IsSourceCodeIncludedExplanation1": "取決於你購買的許可類型:", + "IsSourceCodeIncludedExplanation2": "團隊: 你的解決方案將這些模塊和主題作為NuGet和NPM包使用. 它不包括其源代碼. 這樣,只要有新版本可用,你就可以輕松升級這些模塊和主題. 但是,你無法獲取模塊和主題的源代碼.", + "IsSourceCodeIncludedExplanation3": "商業/企業: 除了團隊許可外,你還可以下載所需的任何模塊或主題的源代碼. 你甚至可以刪除特定模塊的NuGet/NPM軟件包引用,並將其源代碼直接添加到你的解決方案中以完全更改它.", + "IsSourceCodeIncludedExplanation4": "

將模塊的源代碼包含到解決方案中,可以最大程度地自定義該模塊. 但是當新版本發布時,將無法自動升級模塊.

這些許可均不包含ABP Suite源代碼,該源代碼是一個外部工具,可以為你生成代碼並幫助你進行開發

有關許可類型之間的其它差異查看定價頁面.

", + "ChangingDevelopers": "我將來可以更改我組織的註冊開發人員嗎?", + "ChangingDevelopersExplanation": "除了將新的開發人員添加到你的許可中之外,你還可以更改現有的開發人員(可以刪除一個開發人員並將新的開發人員添加到同一位置),而無需任何額外費用.", + "WhatHappensWhenLicenseEnds": "我的許可期限結束後會怎樣?", + "WhatHappensWhenLicenseEndsExplanation1": "ABP商業版具有永久許可類型.許可到期後, 你可以繼續開發你的項目.並且你沒有義務續訂許可.許可到期後;", + "WhatHappensWhenLicenseEndsExplanation2": "你不能使用ABP商業版創建新的解決方案,但可以永遠繼續開發現有的應用程序.", + "WhatHappensWhenLicenseEndsExplanation3": "你能夠在你的主版本中獲得模塊和主題的更新.例如;如果你使用的是模塊的v3.2.0版本,你仍然可以獲得v3.x.x版本的更新.(v3.3.0 v3.5.2…等等)的.但是你無法獲得下一個主要版本(如v4.x,v5.x)的更新", + "WhatHappensWhenLicenseEndsExplanation4": "許可到期後,你無法安裝添加到ABP商業平臺的新模塊和主題.", + "WhatHappensWhenLicenseEndsExplanation5": "你不能使用ABP Suite.", + "WhatHappensWhenLicenseEndsExplanation6": "你不再獲得高級支持.", + "WhatHappensWhenLicenseEndsExplanation7": "如果你想繼續獲得這些好處,可以繼續續訂. 續訂時有20%的折扣.", + "WhenShouldIRenewMyLicense": "我什麽時候應該續訂我的許可?", + "WhenShouldIRenewMyLicenseExplanation1": "如果你在许可到期后的 1个月内续订许可,则许可总价将享受%20的折扣.", + "WhenShouldIRenewMyLicenseExplanation2": "如果你在你的許可過期日期1個月後更新你的許可,更新價格將與許可購買價格相同,你的更新將沒有折扣.", + "TrialPlan": "你們有試用計劃嗎?", + "TrialPlanExplanation": "目前,ABP商業版還沒有試用計劃.對於團隊許可,我們提供30天的退款保證.你可以在30天內要求退款.對於企業營業執照,我們提供30天內60%的退款.這是因為商業和企業許可包含所有模塊和主題的完整源代碼.", + "DoYouAcceptBankWireTransfer": "你們接受銀行電匯嗎?", + "DoYouAcceptBankWireTransferExplanation": "是的,我們接受銀行電匯.
通過銀行電匯轉賬,通過電子郵件將收據和所要求的許可類型發送給我們.
我們的國際銀行帳戶信息:", + "HowToUpgrade": "可用新版本時如何升級現有應用程序?", + "HowToUpgradeExplanation1": "使用ABP商業版創建新應用程序時,所有模塊和主題均用作NuGet和NPM軟件包. 因此,當有新版本可用時,你可以輕松升級軟件包.", + "HowToUpgradeExplanation2": "除了標準的NuGet/NPM升級之外, ABP CLI 還提供了一條更新命令,該命令可自動查找和升級解決方案中的所有與ABP相關的軟件包.", + "DatabaseSupport": "支持哪些數據庫系統?", + "DatabaseSupportExplanation": "ABP框架本身與數據庫無關,並且就其性質而言,可以與任何數據庫提供程序一起使用. 請參閱數據訪問文檔以獲取當前實現的提供程序的列表.", + "UISupport": "支持哪些UI框架?", + "Supported": "支持的", + "UISupportExplanation": "ABP框架本身與UI框架無關,並且可以與任何UI框架一起使用. 但是,並非針對所有UI框架都實現了啟動模板,模塊UI和主題. 有關UI選項的最新列表,請參見入門文檔.", + "MicroserviceSupport": "它是否支持微服務架構?", + "MicroserviceSupportExplanation1": "ABP框架的主要目標之一是為創建微服務解決方案提供便利的基礎架構. 請參閱微服務體系結構文檔,以了解它如何幫助創建微服務系統.", + "MicroserviceSupportExplanation2": "所有的ABP商業模塊通過模塊開發最佳實踐文檔被設計為支持微服務部署場景(使用自己的API和數據庫).", + "MicroserviceSupportExplanation3": "我們提供了一個示例微服務演示解決方案,該示例演示了一種微服務架構實現,可幫助你創建自己的解決方案.", + "MicroserviceSupportExplanation4": "所以簡短的答案是 \"是的, 它支持微服務體系結構\".", + "MicroserviceSupportExplanation5": "但是,微服務系統是一個解決方案,每個解決方案都有不同的要求,網絡拓撲,通信場景,身份驗證可能性,數據庫分離/共享決策,運行時配置,第三方系統集成等等.", + "MicroserviceSupportExplanation6": "ABP框架和ABP商業版提供了微服務方案,微服務兼容模塊,示例和文檔的基礎結構,以幫助你構建自己的解決方案. 但是不要期望直接下載為你預先構建的夢想解決方案. 你將需要了解它,並根據需要將某些部分組合在一起.", + "WhereCanIDownloadSourceCode": "在哪裏可以下載源代碼?", + "WhereCanIDownloadSourceCodeExplanation": "你可以通過ABP Suite或ABP CLI下載所有ABP模塊,Angular軟件包和主題的源代碼. 請參見如何下載源代碼?", + "ComputerLimitation": "開發人員在開發ABP時可以登錄到多少臺計算機?", + "ComputerLimitationExplanation": "我們特別允許每個個人/許可的開發人員使用 {0}臺計算機. 每當需要開發人員在第三臺計算機上開發ABP商業產品時,都應將電子郵件發送到license@abp.io,以說明情況,然後我們將在系統中進行適當分配.", + "RefundPolicy": "你們有退款政策嗎?", + "RefundPolicyExplanation": "你可以在購買許可的30天內請求退款.商業和企業許可類型都有源代碼下載選項,因此商業和企業(以及任何包含獲得源代碼的權利的許可)都不能退款.此外,續展和購買第二次許可也不退款.", + "HowCanIRefundVat": "我該如何退還增值稅?", + "HowCanIRefundVatExplanation1": "如果你使用2Checkout付款,則可以通過2Checkout帳戶退還增值稅:", + "HowCanIRefundVatExplanation2": "登錄到你的2Checkout賬戶", + "HowCanIRefundVatExplanation3": "找到適當的訂單,然後按\"退還已延期的增值稅\"(輸入你的增值稅ID", + "HowCanIGetMyInvoice": "我如何獲得發票?", + "HowCanIGetMyInvoiceExplanation": "有兩個用於購買許可的支付網關:PayU和2Checkout. 如果你通過2Checkout網關購買許可,則它將PDF發票發送到你的電子郵件地址,請參閱2Checkout發票.如果你是通過PayU網關或通過銀行電匯購買的,我們將準備並發送你的發票. 你可以從組織管理頁面索取發票.", + "Forum": "論壇", + "SupportExplanation": "ABP商業版許可包含由ABP框架專家組成的團隊提供的高級論壇支持.", + "PrivateTicket": "私有票", + "PrivateTicketExplanation": "企業許可還包含帶有電子郵件和票系統的私人支持.", + "AbpSuiteExplanation1": "ABP Suite使你在幾分鐘內構建web頁面. 它是一個.NET Core Global工具,可以使用命令行安裝.", + "AbpSuiteExplanation2": "它可以創建一個新的ABP解決方案, 從數據庫生成前端CURD頁面. 有關技術概述查看文檔", + "FastEasy": "快速並且簡單", + "AbpSuiteExplanation3": "ABP Suite允許你輕松的創建CURD頁面. 你只需要定義你的實體和它的屬性, 其它的讓ABP Suite幫你完成! ABP Suite會在幾秒內為你生成CURD頁面和必要的代碼. 它支持Angular, MVC和 Blazor用戶界面.", + "RichOptions": "豐富的選項", + "AbpSuiteExplanation4": "ABP Suite支持多個UI選項,例如 Razor PagesAngular.它還支持多個數據庫, 如 MongoDBEntityFramework Core支持的所有數據庫(MS SQL Server, Oracle, MySql, PostgreSQL 和 更多).", + "AbpSuiteExplanation5": "好消息是, 你不必擔心這些選項. ABP Suite了解你的項目類型並且將生成的代碼放到項目中正確的位置.", + "SourceCode": "源碼", + "AbpSuiteExplanation6": "ABP Suite為你生成源代碼! 它不會生成魔法文件來生成web頁面. ABP Suite為實體, 倉儲, 應用程序, Code First遷移, JavaScript/TypeScript 和 CSHTML/HTML以及必要的頁面生成源代碼. ABP Suite根據軟件開發的最佳實踐來生成代碼, 所以你不必擔心生成的代碼的質量.", + "AbpSuiteExplanation7": "由於你有應用程序層中生成的CURD頁面的構建塊的源代碼, 因此你可以輕松修改源碼並將自定義/業務邏輯註入到所生成的代碼中.", + "CrossPlatform": "跨平台", + "AbpSuiteExplanation8": "ABP Suite使用.NET Core構建並且它是跨平臺的. 它在你的本地電腦中運行為web應用程序. 你可以在Windows, MacLinux上運行它", + "OtherFeatures": "其他功能", + "OtherFeatures1": "輕松更新你的解決方案的NuGetNPM包.", + "OtherFeatures2": "重新生成已經生成的頁面.", + "OtherFeatures3": "創建新的解決方案", + "ThanksForCreatingProject": "感謝你創建你的項目!", + "HotToRunSolution": "如何運行你的解決方案?", + "HotToRunSolutionExplanation": "查看入門文檔來學習如何配置和運行你的解決方案.", + "GettingStarted": "入門", + "WebAppDevTutorial": "Web應用開發教程", + "WebAppDevTutorialExplanation": "查看web應用程序開發教程文檔來一步一步的了解開發示例.", + "Document": "文檔", + "UsingABPSuiteToCURD": "使用ABP Suite來生成CURD頁面", + "SeeABPSuiteDocument": "查看ABP Suite文檔學習如何使用ABP Suite.", + "AskQuestionsOnSupport": "你可以在ABP商業支持提出問題.", + "Documentation": "文檔", + "SeeModulesDocument": "查看模塊文檔獲取所有商業(專業)模塊列表和它們的文檔.", + "Pricing": "價格", + "PricingExplanation": "選擇當前業務需要的特性和功能. 隨著業務增長輕松升級.", + "Team": "團隊", + "Business": "商業", + "Enterprise": "企業", + "Custom": "自定義", + "IncludedDeveloperLicenses": "包括開發人員許可", + "CustomLicenceOrAdditionalServices": "需要自定義許可與額外服務?", + "CustomOrVolumeLicense": "自定義或批量許可", + "LiveTrainingSupport": "現場培訓和支持", + "AndMore": "和更多", + "AdditionalDeveloperLicense": "額外的開發人員許可", + "ProjectCount": "項目數量", + "AllProModules": "所有模塊", + "AllProThemes": "所有主題", + "AllProStartupTemplates": "所有專業啟動模板", + "SourceCodeOfAllModules": "所有模塊的源碼", + "SourceCodeOfAllThemes": "所有主題的源碼", + "PerpetualLicense": "永久的許可", + "UnlimitedServerDeployment": "無限制的服務器部署", + "YearUpgrade": "1年升級", + "YearPremiumForumSupport": "1年高級論壇支持", + "ForumSupportIncidentCountYear": "論壇支持事件數量/年", + "PrivateTicketEmailSupport": "私有票和email支持", + "BuyNow": "現在購買", + "PayViaAmexCard": "我如何通過我的AMEX卡付款?", + "PayViaAmexCardDescription": "由於安全措施,默認付款網關'Iyzico'可能會拒絕某些AMEX信用卡. 在這種情況下,完全可以通過備用付款網關'2Checkout'付款.", + "InvalidReCaptchaErrorMessage": "验证reCAPTCHA时出错,请重试.", + "CompanyName": "公司名稱", + "YourCompanyName": "你的公司名稱", + "FirstName": "名", + "LastName": "姓", + "Optional": "可選的", + "YourFirstName": "你的名字", + "YourLastName": "你的姓氏", + "SpecialOffer": "特別優惠", + "SpecialOfferMessage": "盡快付款,價格在一定時間內有效.", + "DiscountRequest": "折扣申請", + "DiscountRequestDescribeCustomerQuestion": "以下哪個選項描述了你?", + "DiscountRequestStudentEmailMessage": "Email地址必須包含'edu'.", + "DiscountRequestDeveloperCount": "你有多少開發人員?", + "DiscountRequestDeveloperCountExceedMessage": "對於超過 {0} 開發人員的公司,我們不提供折扣.", + "DiscountRequestOrganizationName": "公司/組織/學校名稱", + "Website": "網站", + "GithubUsername": "GitHub用戶名", + "PhoneNumber": "手機號", + "Country": "國家", + "DescribeABPCommercialUsage": "描述你基於ABP商業版進行開發的項目", + "DiscountRequestCertifyInformationMessage": "我證明所有的信息都是真實的.", + "DiscountRequestReceived": "我們收到了你的折扣請求.", + "DiscountRequestStatusMessage": "我們會檢查你提供的信息並且給你答復.", + "MVCOrRazorPages": "MVC (Razor Pages)", + "Angular": "Angular", + "Blazor": "Blazor", + "New": "新的", + "MongoDB": "MongoDB" + } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json index 82033e5849..7be579f1fb 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json @@ -139,6 +139,9 @@ "LinkedinUrlValidationMessage": "Your Linkedin URL can not include whitespace, please be sure your Linkedin URL is correct.", "NoPostsFound": "No posts found!", "SearchInPosts": "Search in posts...", - "MinimumSearchContent": "You must enter at least 3 characters!" + "MinimumSearchContent": "You must enter at least 3 characters!", + "Volo.AbpIo.Domain:060001": "Source URL(\"{ArticleUrl}\") is not Github URL", + "Volo.AbpIo.Domain:060002": "Article Content is not available from Github(\"{ArticleUrl}\") resource.", + "Volo.AbpIo.Domain:060003": "No article content found!" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json new file mode 100644 index 0000000000..cba33bfc30 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json @@ -0,0 +1,144 @@ +{ + "culture": "fi", + "texts": { + "Permission:CommunityArticle": "Yhteisön artikkeli", + "Permission:Edit": "Muokata", + "Waiting": "Odottaa", + "Approved": "Hyväksytty", + "Rejected": "Hylätty", + "Wait": "Odota", + "Approve": "Hyväksyä", + "Reject": "Hylätä", + "ReadArticle": "Lue artikkeli", + "Status": "Tila", + "ContentSource": "Sisältölähde", + "Details": "Yksityiskohdat", + "Url": "URL-osoite", + "Title": "Otsikko", + "CreationTime": "Luomisaika", + "Save": "Tallentaa", + "SameUrlAlreadyExist": "Sama URL-osoite on jo olemassa, jos haluat lisätä tämän artikkelin, vaihda URL-osoite!", + "UrlIsNotValid": "URL-osoite ei kelpaa.", + "UrlNotFound": "URL-osoitetta ei löydy.", + "UrlContentNotFound": "URL-osoitteen sisältöä ei löydy.", + "Summary": "Yhteenveto", + "MostRead": "Luetuimmat", + "Latest": "Viimeisin", + "ContributeAbpCommunity": "Osallistu sivutuotteiden yhteisöön", + "SubmitYourArticle": "Lähetä viesti", + "ContributionGuide": "Contribution Guide", + "BugReport": "Virhe raportti", + "SeeAllArticles": "Katso kaikki viestit", + "WelcomeToABPCommunity!": "Tervetuloa ABP-yhteisöön!", + "MyProfile": "Profiilini", + "MyOrganizations": "Omat organisaatiot", + "EmailNotValid": "Ole hyvä ja syötä toimiva sähköpostiosoite.", + "FeatureRequest": "Ominaisuuspyyntö", + "CreateArticleTitleInfo": "Viestiluettelossa näytettävän viestin nimi.", + "CreateArticleSummaryInfo": "Lyhyt yhteenveto viestistä, joka näytetään postituslistalla.", + "CreateArticleCoverInfo": "Lisää tehokkaan artikkelin luomiseksi kansikuva. Lataa 16: 9-kuvasuhteen kuvat parhaan näkymän saamiseksi. Tiedoston enimmäiskoko: 1 Mt.", + "ThisExtensionIsNotAllowed": "Tätä laajennusta ei sallita.", + "TheFileIsTooLarge": "Tiedosto on liian suuri.", + "GoToTheArticle": "Siirry artikkeliin", + "Contribute": "Osallistu", + "OverallProgress": "Kokonaisedistyminen", + "Done": "Tehty", + "Open": "Avata", + "Closed": "Suljettu", + "LatestQuestionOnThe": "Viimeisin kysymys", + "Stackoverflow": "Pinoaminen", + "Votes": "ääntä", + "Answer": "Vastaus", + "Views": "näkymät", + "Answered": "Vastasi", + "WaitingForYourAnswer": "Odotan vastaustasi", + "Asked": "kysyi", + "AllQuestions": "Kaikki kysymykset", + "NextVersion": "Seuraava versio", + "MilestoneErrorMessage": "Nykyisiä virstanpylväitä koskevia tietoja ei saatu Githubilta.", + "QuestionItemErrorMessage": "Viimeisimmät kysymystiedot Stackoverflow'sta epäonnistui.", + "Oops": "Oho!", + "CreateArticleSuccessMessage": "Artikkeli on lähetetty onnistuneesti. Se julkaistaan sivuston järjestelmänvalvojan tarkistuksen jälkeen.", + "ChooseCoverImage": "Valitse kansikuva ...", + "CoverImage": "Kansikuva", + "ShareYourExperiencesWithTheABPFramework": "Jaa kokemuksesi ABP-puitteista!", + "Optional": "Valinnainen", + "UpdateUserWebSiteInfo": "Esimerkki: https://johndoe.com", + "UpdateUserTwitterInfo": "Esimerkki: johndoe", + "UpdateUserGithubInfo": "Esimerkki: johndoe", + "UpdateUserLinkedinInfo": "Esimerkki: https: //www.linkedin.com / ...", + "UpdateUserCompanyInfo": "Esimerkki: Volosoft", + "UpdateUserJobTitleInfo": "Esimerkki: Ohjelmistokehittäjä", + "UserName": "Käyttäjänimi", + "Company": "Yhtiö", + "PersonalWebsite": "Henkilökohtainen verkkosivusto", + "RegistrationDate": "rekisteröinti päivämäärä", + "Social": "Sosiaalinen", + "Biography": "Elämäkerta", + "HasNoPublishedArticlesYet": "ei ole vielä julkaissut artikkeleita", + "Author": "Kirjoittaja", + "LatestGithubAnnouncements": "Viimeisimmät Github-ilmoitukset", + "SeeAllAnnouncements": "Katso kaikki ilmoitukset", + "LatestBlogPost": "Viimeisin blogiviesti", + "Edit": "Muokata", + "ProfileImageChange": "Vaihda profiilikuva", + "BlogItemErrorMessage": "Viimeisimpiä blogiviestitietoja ei saatu ABP: ltä.", + "PlannedReleaseDate": "Suunniteltu julkaisupäivä", + "CommunityArticleRequestErrorMessage": "Uusinta artikkelipyyntöä ei saatu Githubilta.", + "ArticleRequestFromGithubIssue": "Artikkelipyyntöjä ei ole nyt.", + "LatestArticles": "Uusimmat viestit", + "ArticleRequests": "Artikkelipyynnöt", + "AllArticleRequests": "Katso kaikki artikkelipyynnöt", + "SubscribeToTheNewsletter": "Tilaa uutiskirje", + "NewsletterEmailDefinition": "Hanki tietoa ABP: n tapahtumista, kuten uusista julkaisuista, ilmaisista lähteistä, artikkeleista ja muusta.", + "NoThanks": "Ei kiitos", + "MaybeLater": "Ehkä myöhemmin", + "JoinOurArticleNewsletter": "Liity artikkeliuutiskirjeeseemme", + "Community": "Yhteisö", + "Marketing": "Markkinointi", + "CommunityPrivacyPolicyConfirmation": "Hyväksyn käyttöehdot ja tietosuojakäytännön .", + "ArticleRequestMessageTitle": " Avaa ongelma GitHubissa pyytääksesi artikkelia / opetusohjelmaa, jonka haluat nähdä tällä verkkosivustolla.", + "ArticleRequestMessageBody": "Tässä luettelo yhteisön pyytämistä artikkeleista. Haluatko kirjoittaa pyydetyn artikkelin? Napsauta pyyntöä ja liity keskusteluun.", + "Language": "Kieli", + "CreateArticleLanguageInfo": "Viestin sisällön kieli.", + "VideoPost": "Videoposti", + "Article": "Artikla", + "Read": "Lukea", + "CreateGithubArticleUrlInfo": "Artikkelin alkuperäinen GitHub-URL-osoite.", + "CreateVideoContentUrlInfo": "Viestin alkuperäinen Youtube-URL-osoite.", + "CreateExternalArticleUrlInfo": "Artikkelin alkuperäinen ulkoinen URL-osoite.", + "VideoContentForm": "Lähetä video YouTubessa", + "GithubPostForm": "Lähetä artikkeli GitHubista", + "ExternalPostForm": "Lähetä ulkoinen sisältö", + "HowToPost": "Kuinka lähettää?", + "Posts": "Viestit", + "VideoUrl": "Videon URL-osoite", + "GithubArticleUrl": "Github-artikkelien URL-osoite", + "ExternalArticleUrl": "Ulkoisen artikkelin URL-osoite", + "CreatePostCoverInfo": "Lisää kansikuva, jotta voit luoda tehokkaan viestin. Lataa 16: 9-kuvasuhteen kuvat parhaan näkymän saamiseksi. Tiedoston enimmäiskoko: 1 Mt.", + "ThankYouForContribution": "Kiitos osallistumisesta ABP-yhteisöön.", + "GithubArticle": "Github-artikkeli", + "GithubArticleSubmitStepOne": " 1. Kirjoita artikkeli mistä tahansa julkisesta GitHub-arkistosta Markdown-muodossa. esimerkki ", + "GithubArticleSubmitStepTwo": " 2. Lähetä artikkelin URL-osoite lomaketta käyttämällä.", + "GithubArticleSubmitStepThree": " 3. Artikkelisi renderöidään tällä verkkosivustolla.", + "YoutubeVideo": "Youtube-video", + "YoutubeVideoSubmitStepOne": " 1. Julkaise videosi YouTubessa.", + "YoutubeVideoSubmitStepTwo": " 2. Lähetä videon URL-osoite lomaketta käyttäen.", + "YoutubeVideoSubmitStepThree": " 3. Vierailijat voivat katsella videosisältöäsi suoraan tällä verkkosivustolla.", + "ExternalContent": "Ulkoinen sisältö", + "ExternalContentSubmitStepOne": " 1. Luo sisältöä mille tahansa julkiselle alustalle (media, oma blogi tai mihin tahansa haluat).", + "ExternalContentSubmitStepTwo": " 2. Lähetä sisällön URL-osoite lomaketta käyttämällä.", + "ExternalContentSubmitStepThree": " 3. Vierailijat ohjataan alkuperäisen verkkosivuston sisältöön.", + "ChooseYourContentType": "Valitse tapa, jolla haluat lisätä sisältöä.", + "PostContentViaGithub": "Haluan lisätä artikkelini GitHub -merkintäsääntöjen mukaisesti.", + "PostContentViaYoutube": "Haluan jakaa videoni, jotka ovat käytettävissä Youtube täällä.", + "PostContentViaExternalSource": "Haluan lisätä toisella alustalla julkaisemani sisällön tähän.", + "GitHubUserNameValidationMessage": "Github-käyttäjänimesi ei voi sisältää välilyöntiä. Varmista, että Github-käyttäjänimesi on oikea.", + "PersonalSiteUrlValidationMessage": "Henkilökohtaisen sivuston URL-osoite ei voi sisältää välilyöntiä. Varmista, että henkilökohtaisen sivuston URL-osoite on oikea.", + "TwitterUserNameValidationMessage": "Twitter-käyttäjänimesi ei voi sisältää välilyöntiä. Varmista, että Twitter-käyttäjänimesi on oikea.", + "LinkedinUrlValidationMessage": "Linkedin-URL-osoitteesi ei voi sisältää välilyöntiä. Varmista, että Linkedin-URL-osoitteesi on oikea.", + "NoPostsFound": "Viestejä ei löytynyt!", + "SearchInPosts": "Hae viesteistä ...", + "MinimumSearchContent": "Sinun on annettava vähintään 3 merkkiä!" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json new file mode 100644 index 0000000000..734dadadcd --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json @@ -0,0 +1,144 @@ +{ + "culture": "fr", + "texts": { + "Permission:CommunityArticle": "Article communautaire", + "Permission:Edit": "Éditer", + "Waiting": "Attendre", + "Approved": "Approuvé", + "Rejected": "Rejeté", + "Wait": "Attendez", + "Approve": "Approuver", + "Reject": "Rejeter", + "ReadArticle": "Lire l'article", + "Status": "Statut", + "ContentSource": "Source du contenu", + "Details": "Des détails", + "Url": "URL", + "Title": "Titre", + "CreationTime": "Temps de creation", + "Save": "Sauvegarder", + "SameUrlAlreadyExist": "La même URL existe déjà si vous souhaitez ajouter cet article, vous devez changer l'url!", + "UrlIsNotValid": "L'URL n'est pas valide.", + "UrlNotFound": "URL introuvable.", + "UrlContentNotFound": "Contenu de l'URL introuvable.", + "Summary": "Résumé", + "MostRead": "Les plus lus", + "Latest": "Dernier", + "ContributeAbpCommunity": "Contribuez à la communauté ABP", + "SubmitYourArticle": "Soumettez votre message", + "ContributionGuide": "Guide de contribution", + "BugReport": "Rapport d'erreur", + "SeeAllArticles": "Voir tous les articles", + "WelcomeToABPCommunity!": "Bienvenue dans la communauté ABP!", + "MyProfile": "Mon profil", + "MyOrganizations": "Mes organisations", + "EmailNotValid": "S'il vous plaît, mettez une adresse email valide.", + "FeatureRequest": "Demande de fonctionnalité", + "CreateArticleTitleInfo": "Titre du message à afficher dans la liste des messages.", + "CreateArticleSummaryInfo": "Un bref résumé du message à afficher dans la liste des messages.", + "CreateArticleCoverInfo": "Pour créer un article efficace, ajoutez une photo de couverture. Téléchargez des images au format 16: 9 pour une meilleure vue. Taille maximale du fichier: 1 Mo.", + "ThisExtensionIsNotAllowed": "Cette extension n'est pas autorisée.", + "TheFileIsTooLarge": "Le fichier est trop volumineux.", + "GoToTheArticle": "Aller à l'article", + "Contribute": "Contribuer", + "OverallProgress": "Les progrès d'ensemble", + "Done": "Fait", + "Open": "Ouvert", + "Closed": "Fermé", + "LatestQuestionOnThe": "Dernière question sur le", + "Stackoverflow": "Stackoverflow", + "Votes": "les votes", + "Answer": "Répondre", + "Views": "vues", + "Answered": "Répondu", + "WaitingForYourAnswer": "En attente de votre réponse", + "Asked": "demandé", + "AllQuestions": "Toutes les questions", + "NextVersion": "Version suivante", + "MilestoneErrorMessage": "Impossible d'obtenir les détails de l'étape actuelle à partir de Github.", + "QuestionItemErrorMessage": "Impossible d'obtenir les derniers détails de la question de Stackoverflow.", + "Oops": "Oops!", + "CreateArticleSuccessMessage": "L'article a été soumis avec succès. Il sera publié après un examen de l'administrateur du site.", + "ChooseCoverImage": "Choisissez une image de couverture ...", + "CoverImage": "Image de couverture", + "ShareYourExperiencesWithTheABPFramework": "Partagez vos expériences avec le Framework ABP!", + "Optional": "Optionnel", + "UpdateUserWebSiteInfo": "Exemple: https://johndoe.com", + "UpdateUserTwitterInfo": "Exemple: johndoe", + "UpdateUserGithubInfo": "Exemple: johndoe", + "UpdateUserLinkedinInfo": "Exemple: https: //www.linkedin.com / ...", + "UpdateUserCompanyInfo": "Exemple: Volosoft", + "UpdateUserJobTitleInfo": "Exemple: développeur de logiciels", + "UserName": "Nom d'utilisateur", + "Company": "Compagnie", + "PersonalWebsite": "Site Web personnel", + "RegistrationDate": "Date d'inscription", + "Social": "Social", + "Biography": "Biographie", + "HasNoPublishedArticlesYet": "n'a pas encore d'articles publiés", + "Author": "Auteur", + "LatestGithubAnnouncements": "Dernières annonces Github", + "SeeAllAnnouncements": "Voir toutes les annonces", + "LatestBlogPost": "Dernier article de blog", + "Edit": "Éditer", + "ProfileImageChange": "Changer l'image de profil", + "BlogItemErrorMessage": "Impossible d'obtenir les derniers détails du billet de blog d'ABP.", + "PlannedReleaseDate": "Date de sortie prévue", + "CommunityArticleRequestErrorMessage": "Impossible d'obtenir la dernière demande d'article de Github.", + "ArticleRequestFromGithubIssue": "Il n'y a actuellement aucune demande d'article.", + "LatestArticles": "Derniers messages", + "ArticleRequests": "Demandes d'articles", + "AllArticleRequests": "Voir toutes les demandes d'articles", + "SubscribeToTheNewsletter": "Abonnez-vous à la newsletter", + "NewsletterEmailDefinition": "Obtenez des informations sur les événements d'ABP, comme les nouvelles versions, les sources gratuites, les articles, etc.", + "NoThanks": "Non merci", + "MaybeLater": "Peut-être plus tard", + "JoinOurArticleNewsletter": "Rejoignez notre newsletter d'article", + "Community": "Communauté", + "Marketing": "Commercialisation", + "CommunityPrivacyPolicyConfirmation": "J'accepte les conditions générales et la politique de confidentialité .", + "ArticleRequestMessageTitle": " Ouvrez un problème sur le GitHub pour demander un article / didacticiel que vous souhaitez voir sur ce site Web.", + "ArticleRequestMessageBody": "Ici, la liste des articles demandés par la communauté. Voulez-vous écrire un article demandé? Veuillez cliquer sur la demande et vous joindre à la discussion.", + "Language": "Langue", + "CreateArticleLanguageInfo": "La langue du contenu de l'article.", + "VideoPost": "Message vidéo", + "Article": "Article", + "Read": "Lis", + "CreateGithubArticleUrlInfo": "URL GitHub d'origine de l'article.", + "CreateVideoContentUrlInfo": "URL Youtube d'origine du message.", + "CreateExternalArticleUrlInfo": "URL externe d'origine de l'article.", + "VideoContentForm": "Soumettre une vidéo sur YouTube", + "GithubPostForm": "Soumettre un article sur GitHub", + "ExternalPostForm": "Soumettre un contenu externe", + "HowToPost": "Comment publier?", + "Posts": "Des postes", + "VideoUrl": "URL de la vidéo", + "GithubArticleUrl": "URL de l'article Github", + "ExternalArticleUrl": "URL de l'article externe", + "CreatePostCoverInfo": "Pour créer un article efficace, ajoutez une photo de couverture. Téléchargez des images au format 16: 9 pour une meilleure vue. Taille maximale du fichier: 1 Mo.", + "ThankYouForContribution": "Merci de contribuer à la communauté ABP.", + "GithubArticle": "Article Github", + "GithubArticleSubmitStepOne": " 1. Rédigez un article sur n'importe quel référentiel GitHub public au format Markdown. Exemple de ", + "GithubArticleSubmitStepTwo": " 2. Envoyez l'URL de votre article à l'aide du formulaire.", + "GithubArticleSubmitStepThree": " 3. Votre article sera rendu sur ce site Web.", + "YoutubeVideo": "Vidéo Youtube", + "YoutubeVideoSubmitStepOne": " 1. Publiez votre vidéo sur YouTube.", + "YoutubeVideoSubmitStepTwo": " 2. Envoyez l'URL de la vidéo à l'aide du formulaire.", + "YoutubeVideoSubmitStepThree": " 3. Les visiteurs pourront visionner votre contenu vidéo directement sur ce site Web.", + "ExternalContent": "Contenu externe", + "ExternalContentSubmitStepOne": " 1. Créez un contenu sur n'importe quelle plate-forme publique (support, votre propre blog ou partout où vous le souhaitez).", + "ExternalContentSubmitStepTwo": " 2. Envoyez votre URL de contenu à l'aide du formulaire.", + "ExternalContentSubmitStepThree": " 3. Les visiteurs sont redirigés vers le contenu du site Web d'origine.", + "ChooseYourContentType": "Veuillez choisir la manière dont vous souhaitez ajouter votre contenu.", + "PostContentViaGithub": "Je souhaite ajouter mon article avec GitHub conformément aux règles de démarque.", + "PostContentViaYoutube": "Je souhaite partager mes vidéos disponibles sur Youtube ici.", + "PostContentViaExternalSource": "Je souhaite ajouter le contenu que j'ai publié sur une autre plate-forme ici.", + "GitHubUserNameValidationMessage": "Votre nom d'utilisateur Github ne peut pas inclure d'espaces, veuillez vous assurer que votre nom d'utilisateur Github est correct.", + "PersonalSiteUrlValidationMessage": "L'URL de votre site personnel ne peut pas inclure d'espaces, veuillez vous assurer que l'URL de votre site personnel est correcte.", + "TwitterUserNameValidationMessage": "Votre nom d'utilisateur Twitter ne peut pas inclure d'espaces, veuillez vous assurer que votre nom d'utilisateur Twitter est correct.", + "LinkedinUrlValidationMessage": "Votre URL Linkedin ne peut pas inclure d'espace blanc, veuillez vous assurer que votre URL Linkedin est correcte.", + "NoPostsFound": "Aucun article trouvé!", + "SearchInPosts": "Rechercher dans les messages ...", + "MinimumSearchContent": "Vous devez saisir au moins 3 caractères!" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json new file mode 100644 index 0000000000..a3f824d6ba --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json @@ -0,0 +1,147 @@ +{ + "culture": "hi", + "texts": { + "Permission:CommunityArticle": "सामुदायिक अनुच्छेद", + "Permission:Edit": "संपादित करें", + "Waiting": "इंतज़ार कर रही", + "Approved": "मंजूर की", + "Rejected": "अस्वीकृत", + "Wait": "रुको", + "Approve": "मंजूर", + "Reject": "अस्वीकार", + "ReadArticle": "लेख पढ़ें", + "Status": "स्थिति", + "ContentSource": "विषय - वस्तु का स्रोत", + "Details": "विवरण", + "Url": "यूआरएल", + "Title": "शीर्षक", + "CreationTime": "रचना समय", + "Save": "सहेजें", + "SameUrlAlreadyExist": "वही url पहले से मौजूद है यदि आप इस लेख को जोड़ना चाहते हैं, तो आपको url को बदल देना चाहिए!", + "UrlIsNotValid": "यू आर एल मान्य नहीं है।", + "UrlNotFound": "Url नहीं मिला।", + "UrlContentNotFound": "यूआरएल सामग्री नहीं मिली।", + "Summary": "सारांश", + "MostRead": "सबसे ज़्यादा पढ़ा हुआ", + "Latest": "नवीनतम", + "ContributeAbpCommunity": "ABP समुदाय में योगदान दें", + "SubmitYourArticle": "अपनी पोस्ट सबमिट करें", + "ContributionGuide": "योगदान गाइड", + "BugReport": "बग रिपोर्ट", + "SeeAllArticles": "सभी पोस्ट देखें", + "WelcomeToABPCommunity!": "ABP समुदाय में आपका स्वागत है!", + "MyProfile": "मेरी प्रोफाइल", + "MyOrganizations": "मेरे संगठन", + "EmailNotValid": "कृपया एक वैध ई - मेल एड्रेस डालें।", + "FeatureRequest": "महत्वपूर्ण लेख मांगना", + "CreateArticleTitleInfo": "पोस्ट का शीर्षक पोस्ट सूची पर दिखाया जाना है।", + "CreateArticleSummaryInfo": "पोस्ट सूची पर दिखाए जाने वाले पोस्ट का संक्षिप्त सारांश।", + "CreateArticleCoverInfo": "एक प्रभावी लेख बनाने के लिए, एक कवर फ़ोटो जोड़ें। सर्वश्रेष्ठ दृश्य के लिए 16: 9 पहलू अनुपात चित्र अपलोड करें। अधिकतम फ़ाइल आकार: 1 एमबी।", + "ThisExtensionIsNotAllowed": "इस एक्सटेंशन की अनुमति नहीं है।", + "TheFileIsTooLarge": "फ़ाइल बहुत बड़ी है।", + "GoToTheArticle": "लेख पर जाएं", + "Contribute": "योगदान", + "OverallProgress": "समग्र प्रगति", + "Done": "किया हुआ", + "Open": "खुला हुआ", + "Closed": "बंद किया हुआ", + "LatestQuestionOnThe": "पर नवीनतम प्रश्न", + "Stackoverflow": "स्टैक ओवरफ़्लो", + "Votes": "वोट", + "Answer": "उत्तर", + "Views": "विचारों", + "Answered": "उत्तर", + "WaitingForYourAnswer": "आपके जवाब का इंतज़ार", + "Asked": "पूछा", + "AllQuestions": "सभी प्रश्न", + "NextVersion": "अगला संस्करण", + "MilestoneErrorMessage": "Github से वर्तमान मील का पत्थर का विवरण नहीं मिल सका।", + "QuestionItemErrorMessage": "Stackoverflow से नवीनतम प्रश्न विवरण प्राप्त नहीं कर सका।", + "Oops": "उफ़!", + "CreateArticleSuccessMessage": "अनुच्छेद सफलतापूर्वक प्रस्तुत किया गया है। इसे साइट व्यवस्थापक से समीक्षा के बाद प्रकाशित किया जाएगा।", + "ChooseCoverImage": "कवर छवि चुनें ...", + "CoverImage": "कवर छवि", + "ShareYourExperiencesWithTheABPFramework": "ABP फ्रेमवर्क के साथ अपने अनुभव साझा करें!", + "Optional": "ऐच्छिक", + "UpdateUserWebSiteInfo": "उदाहरण: https://johndoe.com", + "UpdateUserTwitterInfo": "उदाहरण: जॉन्डो", + "UpdateUserGithubInfo": "उदाहरण: जॉन्डो", + "UpdateUserLinkedinInfo": "उदाहरण: https: //www.linkedin.com / ...", + "UpdateUserCompanyInfo": "उदाहरण: वोलोसॉफ्ट", + "UpdateUserJobTitleInfo": "उदाहरण: सॉफ्टवेयर डेवलपर", + "UserName": "उपयोगकर्ता नाम", + "Company": "कंपनी", + "PersonalWebsite": "व्यक्तिगत वेबसाइट", + "RegistrationDate": "पंजीकरण की तारीख", + "Social": "सामाजिक", + "Biography": "जीवनी", + "HasNoPublishedArticlesYet": "अभी तक कोई प्रकाशित लेख नहीं है", + "Author": "लेखक", + "LatestGithubAnnouncements": "नवीनतम गितूब घोषणाएँ", + "SeeAllAnnouncements": "सभी घोषणाएँ देखें", + "LatestBlogPost": "नवीनतम ब्लॉग पोस्ट", + "Edit": "संपादित करें", + "ProfileImageChange": "प्रोफ़ाइल छवि बदलें", + "BlogItemErrorMessage": "ABP से नवीनतम ब्लॉग पोस्ट विवरण नहीं मिल सका।", + "PlannedReleaseDate": "योजना जारी करने की तारीख", + "CommunityArticleRequestErrorMessage": "जीथब से नवीनतम लेख अनुरोध नहीं मिल सका।", + "ArticleRequestFromGithubIssue": "अब कोई लेख अनुरोध नहीं है।", + "LatestArticles": "नवीनतम पोस्ट", + "ArticleRequests": "लेख अनुरोध", + "AllArticleRequests": "सभी लेख अनुरोध देखें", + "SubscribeToTheNewsletter": "न्यूज़लेटर की सदस्यता लें", + "NewsletterEmailDefinition": "एबीपी में होने वाली घटनाओं के बारे में जानकारी प्राप्त करें जैसे नए रिलीज़, मुफ्त स्रोत, लेख, और बहुत कुछ।", + "NoThanks": "जी नहीं, धन्यवाद", + "MaybeLater": "शायद बाद में", + "JoinOurArticleNewsletter": "हमारे लेख समाचार पत्र में शामिल हों", + "Community": "समुदाय", + "Marketing": "विपणन", + "CommunityPrivacyPolicyConfirmation": "मैं नियम और शर्तों और गोपनीयता नीति से सहमत हूं।", + "ArticleRequestMessageTitle": "GitHub पर एक लेख / ट्यूटोरियल जिसे आप इस वेब साइट पर देखना चाहते हैं, का अनुरोध करने के लिए एक समस्या खोलें ।", + "ArticleRequestMessageBody": "यहाँ, समुदाय द्वारा अनुरोधित लेखों की सूची। क्या आप एक अनुरोधित लेख लिखना चाहते हैं? कृपया अनुरोध पर क्लिक करें और चर्चा में शामिल हों।", + "Language": "भाषा: हिन्दी", + "CreateArticleLanguageInfo": "पोस्ट सामग्री के लिए भाषा।", + "VideoPost": "वीडियो पोस्ट", + "Article": "लेख", + "Read": "पढ़ें", + "CreateGithubArticleUrlInfo": "मूल GitHub लेख का URL।", + "CreateVideoContentUrlInfo": "पोस्ट का मूल Youtube URL।", + "CreateExternalArticleUrlInfo": "लेख के मूल बाहरी यूआरएल।", + "VideoContentForm": "YouTube पर वीडियो सबमिट करें", + "GithubPostForm": "GitHub पर लेख प्रस्तुत करें", + "ExternalPostForm": "एक बाहरी सामग्री सबमिट करें", + "HowToPost": "पोस्ट कैसे करें?", + "Posts": "पदों", + "VideoUrl": "वीडियो यूआरएल", + "GithubArticleUrl": "गीथब लेख उराल", + "ExternalArticleUrl": "बाहरी लेख यूआरएल", + "CreatePostCoverInfo": "एक प्रभावी पोस्ट बनाने के लिए, एक कवर फ़ोटो जोड़ें। सर्वश्रेष्ठ दृश्य के लिए 16: 9 पहलू अनुपात चित्र अपलोड करें। अधिकतम फ़ाइल आकार: 1 एमबी।", + "ThankYouForContribution": "ABP समुदाय में योगदान के लिए धन्यवाद।", + "GithubArticle": "गीथब लेख", + "GithubArticleSubmitStepOne": " 1। मार्कडाउन प्रारूप के साथ किसी भी सार्वजनिक GitHub रिपॉजिटरी पर एक लेख लिखें। उदाहरण ", + "GithubArticleSubmitStepTwo": " 2। फ़ॉर्म का उपयोग करके अपना लेख URL सबमिट करें।", + "GithubArticleSubmitStepThree": " 3। इस वेब साइट में आपका लेख प्रस्तुत किया जाएगा।", + "YoutubeVideo": "यूट्यूब वीडियो", + "YoutubeVideoSubmitStepOne": " 1। YouTube पर अपना वीडियो प्रकाशित करें।", + "YoutubeVideoSubmitStepTwo": " 2। फ़ॉर्म का उपयोग करके वीडियो URL सबमिट करें।", + "YoutubeVideoSubmitStepThree": " 3। आगंतुक इस वेबसाइट पर सीधे आपकी वीडियो सामग्री देख सकेंगे।", + "ExternalContent": "बाहरी सामग्री", + "ExternalContentSubmitStepOne": " 1। किसी भी सार्वजनिक मंच पर एक सामग्री बनाएं (मध्यम, अपना स्वयं का ब्लॉग या कहीं भी आप चाहें)।", + "ExternalContentSubmitStepTwo": " 2। फ़ॉर्म का उपयोग करके अपना सामग्री URL सबमिट करें।", + "ExternalContentSubmitStepThree": " 3। मूल वेबसाइट पर आगंतुकों को सामग्री पर पुनर्निर्देशित किया गया है।", + "ChooseYourContentType": "कृपया अपनी सामग्री जोड़ने का तरीका चुनें।", + "PostContentViaGithub": "मैं अपना लेख जोड़ना चाहता हूं GitHub अंकन नियमों के अनुसार।", + "PostContentViaYoutube": "मैं यहां उपलब्ध अपने वीडियो को Youtube पर साझा करना चाहता हूं।", + "PostContentViaExternalSource": "मैं यहां एक अन्य प्लेटफ़ॉर्म पर प्रकाशित सामग्री जोड़ना चाहता हूं।", + "GitHubUserNameValidationMessage": "आपके Github उपयोगकर्ता नाम में व्हॉट्सएप शामिल नहीं हो सकता है, कृपया सुनिश्चित करें कि आपका Github उपयोगकर्ता नाम सही है।", + "PersonalSiteUrlValidationMessage": "आपके व्यक्तिगत साइट URL में व्हॉट्सएप शामिल नहीं हो सकता है, कृपया सुनिश्चित करें कि आपका व्यक्तिगत साइट URL सही है।", + "TwitterUserNameValidationMessage": "आपके ट्विटर उपयोगकर्ता नाम में व्हाट्सएप शामिल नहीं हो सकता है, कृपया सुनिश्चित करें कि आपका ट्विटर उपयोगकर्ता नाम सही है।", + "LinkedinUrlValidationMessage": "आपके लिंक्डइन URL में व्हॉट्सएप शामिल नहीं हो सकता है, कृपया सुनिश्चित करें कि आपका लिंक्डइन URL सही है।", + "NoPostsFound": "कोई प्रकाशन नहीं मिला!", + "SearchInPosts": "पदों में खोजें ...", + "MinimumSearchContent": "आपको कम से कम 3 वर्ण दर्ज करने होंगे!", + "Volo.AbpIo.Domain:060001": "स्रोत URL (\"{ArticleUrl}\") जीथब URL नहीं है", + "Volo.AbpIo.Domain:060002": "लेख सामग्री Github (\"{ArticleUrl}\") संसाधन से उपलब्ध नहीं है।", + "Volo.AbpIo.Domain:060003": "कोई लेख सामग्री नहीं मिली!" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json new file mode 100644 index 0000000000..6e8dfc31e7 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json @@ -0,0 +1,147 @@ +{ + "culture": "it", + "texts": { + "Permission:CommunityArticle": "Articolo comunitario", + "Permission:Edit": "modificare", + "Waiting": "In attesa", + "Approved": "Approvato", + "Rejected": "Respinto", + "Wait": "Aspettare", + "Approve": "Approvare", + "Reject": "Rifiutare", + "ReadArticle": "Leggi l'articolo", + "Status": "Stato", + "ContentSource": "Fonte di contenuto", + "Details": "Dettagli", + "Url": "Url", + "Title": "Titolo", + "CreationTime": "Tempo di creazione", + "Save": "Salva", + "SameUrlAlreadyExist": "Lo stesso URL esiste già se vuoi aggiungere questo articolo, dovresti cambiare l'URL!", + "UrlIsNotValid": "URL non valido.", + "UrlNotFound": "URL non trovato.", + "UrlContentNotFound": "Contenuto URL non trovato.", + "Summary": "Sommario", + "MostRead": "I più letti", + "Latest": "Ultimo", + "ContributeAbpCommunity": "Contribuisci alla comunità ABP", + "SubmitYourArticle": "Invia il tuo post", + "ContributionGuide": "Guida al contributo", + "BugReport": "Riportare un errore", + "SeeAllArticles": "Vedi tutti i post", + "WelcomeToABPCommunity!": "Benvenuto nella comunità ABP!", + "MyProfile": "Il mio profilo", + "MyOrganizations": "Le mie organizzazioni", + "EmailNotValid": "Si prega di inserire un indirizzo email valido.", + "FeatureRequest": "Richiesta di funzionalità", + "CreateArticleTitleInfo": "Titolo del post da mostrare nell'elenco dei post.", + "CreateArticleSummaryInfo": "Un breve riassunto del post da mostrare nell'elenco dei post.", + "CreateArticleCoverInfo": "Per creare un articolo efficace, aggiungi una foto di copertina. Carica immagini in formato 16: 9 per una visualizzazione migliore. Dimensione massima del file: 1 MB.", + "ThisExtensionIsNotAllowed": "Questa estensione non è consentita.", + "TheFileIsTooLarge": "Il file è troppo grande.", + "GoToTheArticle": "Vai all'articolo", + "Contribute": "Contribuire", + "OverallProgress": "Progressi generali", + "Done": "Fatto", + "Open": "Aperto", + "Closed": "Chiuso", + "LatestQuestionOnThe": "Ultima domanda su", + "Stackoverflow": "Stackoverflow", + "Votes": "voti", + "Answer": "Risposta", + "Views": "visualizzazioni", + "Answered": "Risposto", + "WaitingForYourAnswer": "In attesa della tua risposta", + "Asked": "chiesto", + "AllQuestions": "Tutte le domande", + "NextVersion": "Versione successiva", + "MilestoneErrorMessage": "Impossibile ottenere i dettagli della pietra miliare corrente da Github.", + "QuestionItemErrorMessage": "Impossibile ottenere gli ultimi dettagli della domanda da Stackoverflow.", + "Oops": "Ops!", + "CreateArticleSuccessMessage": "L'articolo è stato inviato con successo. Verrà pubblicato dopo una revisione da parte dell'amministratore del sito.", + "ChooseCoverImage": "Scegli un'immagine di copertina ...", + "CoverImage": "Immagine di copertina", + "ShareYourExperiencesWithTheABPFramework": "Condividi le tue esperienze con ABP Framework!", + "Optional": "Opzionale", + "UpdateUserWebSiteInfo": "Esempio: https://johndoe.com", + "UpdateUserTwitterInfo": "Esempio: johndoe", + "UpdateUserGithubInfo": "Esempio: johndoe", + "UpdateUserLinkedinInfo": "Esempio: https: //www.linkedin.com / ...", + "UpdateUserCompanyInfo": "Esempio: Volosoft", + "UpdateUserJobTitleInfo": "Esempio: sviluppatore di software", + "UserName": "Nome utente", + "Company": "Azienda", + "PersonalWebsite": "Sito web personale", + "RegistrationDate": "Data di registrazione", + "Social": "Sociale", + "Biography": "Biografia", + "HasNoPublishedArticlesYet": "non ha ancora articoli pubblicati", + "Author": "Autore", + "LatestGithubAnnouncements": "Ultimi annunci su GitHub", + "SeeAllAnnouncements": "Vedi tutti gli annunci", + "LatestBlogPost": "Ultimo post sul blog", + "Edit": "modificare", + "ProfileImageChange": "Cambia l'immagine del profilo", + "BlogItemErrorMessage": "Impossibile ottenere i dettagli più recenti del post del blog da ABP.", + "PlannedReleaseDate": "Data di rilascio prevista", + "CommunityArticleRequestErrorMessage": "Impossibile ottenere l'ultima richiesta di articolo da Github.", + "ArticleRequestFromGithubIssue": "Non ci sono richieste di articoli al momento.", + "LatestArticles": "ultimi post", + "ArticleRequests": "Richieste di articoli", + "AllArticleRequests": "Vedi tutte le richieste di articoli", + "SubscribeToTheNewsletter": "Iscriviti alla Newsletter", + "NewsletterEmailDefinition": "Ottieni informazioni sugli eventi in ABP come nuove versioni, fonti gratuite, articoli e altro ancora.", + "NoThanks": "No grazie", + "MaybeLater": "Forse più tardi", + "JoinOurArticleNewsletter": "Iscriviti alla nostra newsletter articolo", + "Community": "Comunità", + "Marketing": "Marketing", + "CommunityPrivacyPolicyConfirmation": "Accetto i Termini e condizioni e l ' Informativa sulla privacy .", + "ArticleRequestMessageTitle": " Apri un numero su GitHub per richiedere un articolo / tutorial che desideri vedere su questo sito web.", + "ArticleRequestMessageBody": "Di seguito l'elenco degli articoli richiesti dalla community. Vuoi scrivere un articolo richiesto? Fare clic sulla richiesta e partecipare alla discussione.", + "Language": "linguaggio", + "CreateArticleLanguageInfo": "La lingua per il contenuto del post.", + "VideoPost": "Post video", + "Article": "Articolo", + "Read": "Leggere", + "CreateGithubArticleUrlInfo": "URL originale di GitHub dell'articolo.", + "CreateVideoContentUrlInfo": "URL YouTube originale del post.", + "CreateExternalArticleUrlInfo": "URL esterno originale dell'articolo.", + "VideoContentForm": "Invia video su YouTube", + "GithubPostForm": "Invia articolo su GitHub", + "ExternalPostForm": "Invia un contenuto esterno", + "HowToPost": "Come pubblicare?", + "Posts": "Messaggi", + "VideoUrl": "URL video", + "GithubArticleUrl": "URL articolo Github", + "ExternalArticleUrl": "URL articolo esterno", + "CreatePostCoverInfo": "Per creare un post efficace, aggiungi una foto di copertina. Carica immagini in formato 16: 9 per una visualizzazione migliore. Dimensione massima del file: 1 MB.", + "ThankYouForContribution": "Grazie per aver contribuito alla comunità ABP.", + "GithubArticle": "Articolo GitHub", + "GithubArticleSubmitStepOne": " 1. Scrivi un articolo su qualsiasi repository GitHub pubblico con il formato Markdown. esempio ", + "GithubArticleSubmitStepTwo": " 2. Invia l'URL del tuo articolo utilizzando il modulo.", + "GithubArticleSubmitStepThree": " 3. Il tuo articolo verrà visualizzato in questo sito web.", + "YoutubeVideo": "Video Youtube", + "YoutubeVideoSubmitStepOne": " 1. Pubblica il tuo video su YouTube.", + "YoutubeVideoSubmitStepTwo": " 2. Invia l'URL del video utilizzando il modulo.", + "YoutubeVideoSubmitStepThree": " 3. I visitatori potranno guardare i tuoi contenuti video direttamente su questo sito web.", + "ExternalContent": "Contenuto esterno", + "ExternalContentSubmitStepOne": " 1. Crea un contenuto su qualsiasi piattaforma pubblica (mezzo, il tuo blog o ovunque tu voglia).", + "ExternalContentSubmitStepTwo": " 2. Invia l'URL dei tuoi contenuti utilizzando il modulo.", + "ExternalContentSubmitStepThree": " 3. I visitatori vengono reindirizzati al contenuto del sito web originale.", + "ChooseYourContentType": "Scegli il modo in cui desideri aggiungere i tuoi contenuti.", + "PostContentViaGithub": "Voglio aggiungere il mio articolo con GitHub in conformità con le regole di markdown.", + "PostContentViaYoutube": "Voglio condividere i miei video disponibili su Youtube qui.", + "PostContentViaExternalSource": "Voglio aggiungere qui il contenuto che ho pubblicato su un'altra piattaforma .", + "GitHubUserNameValidationMessage": "Il tuo nome utente Github non può includere spazi bianchi, assicurati che il tuo nome utente Github sia corretto.", + "PersonalSiteUrlValidationMessage": "L'URL del tuo sito personale non può includere spazi bianchi, assicurati che l'URL del tuo sito personale sia corretto.", + "TwitterUserNameValidationMessage": "Il tuo nome utente Twitter non può includere spazi bianchi, assicurati che il tuo nome utente Twitter sia corretto.", + "LinkedinUrlValidationMessage": "Il tuo URL di Linkedin non può includere spazi bianchi, assicurati che il tuo URL di Linkedin sia corretto.", + "NoPostsFound": "Nessun post trovato!", + "SearchInPosts": "Cerca nei post ...", + "MinimumSearchContent": "Devi inserire almeno 3 caratteri!", + "Volo.AbpIo.Domain:060001": "L'URL di origine (\"{ArticleUrl}\") non è l'URL di GitHub", + "Volo.AbpIo.Domain:060002": "Il contenuto dell'articolo non è disponibile dalla risorsa Github (\"{ArticleUrl}\").", + "Volo.AbpIo.Domain:060003": "Nessun contenuto dell'articolo trovato!" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json index c0a168a6c2..f99dee2c0e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json @@ -194,6 +194,41 @@ "MultipleUIOptionsExplanation": "The core framework is designed as UI independent and can work with any type of UI system, while there are multiple pre-built and integrated options are provided out of the box.", "MultipleDBOptionsExplanation": "The framework can work with any data source, while the following providers are officially developed and supported:", "SelectLanguage": "Select language", - "LatestArticleOnCommunity": "Latest Article on ABP Community" + "LatestArticleOnCommunity": "Latest Article on ABP Community", + "Register": "Register", + "IsDownloadable": "Is downloadable", + "DatabaseOptions": "Database Options", + "BackToPackagesPage": "Back to Packages Page", + "HowToInstall": "How to Install", + "SeeOnNpm": "See on NPM", + "SeeOnNuget": "See on Nuget", + "MVCGulpCommandExplanation": "If you are using MVC (Razor Pages) UI, then run the \"gulp\" command after the package installation.", + "UsingABPCLI": "Using Abp CLI", + "WithoutABPCLI": "Without ABP CLI", + "ABPCLIModuleDependency": "Abp Cli automatically adds module dependency.", + "AddModuleDependency": "Then add module dependency", + "Packages": "Packages", + "NugetPackages": "Nuget Packages", + "NPMPackages": "NPM Packages", + "SeeDocs": "See Docs", + "None": "None", + "Application": "Application", + "Module": "Module", + "PackageName": "Package Name", + "LicenseURL": "License URL", + "License": "License", + "ProjectCreationSuccessMessage": "Your project has been successfully created", + "HowToRunSolution": "How to Run Your Solution?", + "GettingStartedMessage": "See getting started document to learn how to configure and run your solution.", + "WebAppDevTutorial": "Web App Dev Tutorial", + "WebAppDevTutorialMessage": "See web application development tutorial document for a step by step development sample.", + "CommunityArticles": "Community Articles", + "CommunityArticleMessage": "Check ABP Community Platform to read useful articles for ABP Framework.", + "InvestigateSolutionDetails": "Investigate the Solution Details", + "StartupTemplateDocumentationMessage": "See application startup template document to learn the architecture and the structure of your solution.", + "ClientSideDevelopment": "Client Side Development", + "ClientSideDevelopmentDocumentationMessage": "See the {0} document to learn key points for user interface (client side) development.", + "DatabaseProviderDocumentationMessage": "See {0} document to learn key points for database layer development.", + "ABPCommercialExplanationMessage": "ABP Commercial provides premium modules, themes, tooling and support for the ABP Framework." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index 0edbb7a5dc..a24931dab5 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -175,7 +175,7 @@ "TieredOption": "Creates a tiered solution where Web and Http API layers are physically separated. If not checked, creates a layered solution which is less complex and suitable for most scenarios.", "SeparateIdentityServerOption": "Separates server side into two applications: First one is for the identity server and the second one is for your server side HTTP API.", "UseslatestPreVersion": "Uses latest pre-release version", - "ReadTheDocumentation": "ReadThe Documentation", + "ReadTheDocumentation": "Read The Documentation", "Documentation": "Documentation", "GettingStartedTutorial": "Getting Started Tutorial", "ApplicationDevelopmentTutorial": "Application Development Tutorial", @@ -195,8 +195,41 @@ "MultipleUIOptionsExplanation": "The core framework is designed as UI independent and can work with any type of UI system, while there are multiple pre-built and integrated options are provided out of the box.", "MultipleDBOptionsExplanation": "The framework can work with any data source, while the following providers are officially developed and supported;", "SelectLanguage": "Select language", - "LatestArticleOnCommunity": "Latest Article on ABP Community", - "Register": "Register", - "IsDownloadable": "Is downloadable" + "LatestArticleOnCommunity": "Latest Article on ABP Community", + "Register": "Register", + "IsDownloadable": "Is downloadable", + "DatabaseOptions": "Database Options", + "BackToPackagesPage": "Back to Packages Page", + "HowToInstall": "How to Install", + "SeeOnNpm": "See on NPM", + "SeeOnNuget": "See on Nuget", + "MVCGulpCommandExplanation": "If you are using MVC (Razor Pages) UI, then run the \"gulp\" command after the package installation.", + "UsingABPCLI": "Using Abp CLI", + "WithoutABPCLI": "Without ABP CLI", + "ABPCLIModuleDependency": "Abp Cli automatically adds module dependency.", + "AddModuleDependency": "Then add module dependency", + "Packages": "Packages", + "NugetPackages": "Nuget Packages", + "NPMPackages": "NPM Packages", + "SeeDocs": "See Docs", + "None": "None", + "Application": "Application", + "Module": "Module", + "PackageName": "Package Name", + "LicenseURL": "License URL", + "License": "License", + "ProjectCreationSuccessMessage": "Your project has been successfully created", + "HowToRunSolution": "How to Run Your Solution?", + "GettingStartedMessage": "See getting started document to learn how to configure and run your solution.", + "WebAppDevTutorial": "Web App Dev Tutorial", + "WebAppDevTutorialMessage": "See web application development tutorial document for a step by step development sample.", + "CommunityArticles": "Community Articles", + "CommunityArticleMessage": "Check ABP Community Platform to read useful articles for ABP Framework.", + "InvestigateSolutionDetails": "Investigate the Solution Details", + "StartupTemplateDocumentationMessage": "See application startup template document to learn the architecture and the structure of your solution.", + "ClientSideDevelopment": "Client Side Development", + "ClientSideDevelopmentDocumentationMessage": "See the {0} document to learn key points for user interface (client side) development.", + "DatabaseProviderDocumentationMessage": "See {0} document to learn key points for database layer development.", + "ABPCommercialExplanationMessage": "ABP Commercial provides premium modules, themes, tooling and support for the ABP Framework." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json new file mode 100644 index 0000000000..9b15582b38 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json @@ -0,0 +1,202 @@ +{ + "culture": "fi", + "texts": { + "GetStarted": "Aloitus - Käynnistysmallit", + "Create": "Luoda", + "NewProject": "Uusi projekti", + "DirectDownload": "Suora lataus", + "ProjectName": "Projektin nimi", + "ProjectType": "Projektityyppi", + "DatabaseProvider": "Tietokannan tarjoaja", + "DatabaseManagementSystem": "Tietokannan ohjausjärjestelmä", + "NTier": "N-taso", + "IncludeUserInterface": "Sisällytä käyttöliittymä", + "CreateNow": "Luo nyt", + "TheStartupProject": "Käynnistysprojekti", + "Tutorial": "Opetusohjelma", + "UsingCLI": "CLI: n käyttö", + "SeeDetails": "Katso yksityiskohdat", + "AbpShortDescription": "ABP Framework on täydellinen infrastruktuuri nykyaikaisten verkkosovellusten luomiseen noudattamalla ohjelmistokehityksen parhaita käytäntöjä ja käytäntöjä.", + "SourceCodeUpper": "LÄHDEKOODI", + "LatestReleaseLogs": "Uusimmat julkaisulokit", + "Infrastructure": "Infrastruktuuri", + "Architecture": "Arkkitehtuuri", + "Modular": "Modulaarinen", + "DontRepeatYourself": "Älä toista itseäsi", + "DeveloperFocused": "Kehittäjä kohdennettu", + "FullStackApplicationInfrastructure": "Täyden pinon sovellusinfrastruktuuri.", + "DomainDrivenDesign": "Toimialueohjattu suunnittelu", + "DomainDrivenDesignExplanation": "Suunniteltu ja kehitetty DDD-mallien ja -periaatteiden perusteella. Tarjoaa kerrostetun mallin sovelluksellesi.", + "Authorization": "Valtuutus", + "AuthorizationExplanation": "Edistynyt käyttöoikeudet käyttäjän, roolin ja tarkan käyttöjärjestelmän avulla. Rakennettu Microsoft Identity -kirjastoon.", + "MultiTenancy": "Monivuokraus", + "MultiTenancyExplanationShort": "SaaS-sovellukset on tehty helpoksi! Integroitu monivuokraus tietokannasta käyttöliittymään.", + "CrossCuttingConcerns": "Laaja-alaiset huolenaiheet", + "CrossCuttingConcernsExplanationShort": "Täydellinen infrastruktuuri valtuutusta, validointia, poikkeusten käsittelyä, välimuistia, auditointilokia, tapahtumien hallintaa ja muuta varten.", + "BuiltInBundlingMinification": "Sisäänrakennettu niputtaminen ja pienentäminen", + "BuiltInBundlingMinificationExplanation": "Niputtamiseen ja pienentämiseen ei tarvitse käyttää ulkoisia työkaluja. ABP tarjoaa yksinkertaisemman, dynaamisemman, tehokkaamman, modulaarisemman ja sisäänrakennetun tavan!", + "VirtualFileSystem": "Virtuaalinen tiedostojärjestelmä", + "VirtualFileSystemExplanation": "Upota näkymät, komentosarjat, tyylit, kuvat ... paketteihin / kirjastoihin ja käytä niitä uudelleen eri sovelluksissa.", + "Theming": "Heidät", + "ThemingExplanationShort": "Käytä ja muokkaa bootstrap-pohjaista vakiokäyttöliittymän teemaa tai luo oma.", + "BootstrapTagHelpersDynamicForms": "Bootstrap Tag Helpers ja dynaamiset lomakkeet", + "BootstrapTagHelpersDynamicFormsExplanation": "Sen sijaan, että kirjoittaisit manuaalisesti käynnistysstrap-komponenttien toistuvia yksityiskohtia, käytä ABP: n tag-avustajia yksinkertaistaaksesi sitä ja hyödyntääksesi älykkäitä ominaisuuksia. Rakenna käyttöliittymälomakkeet nopeasti C # -mallin perusteella käyttämällä dynaamista lomaketunnisteen auttajaa.", + "HTTPAPIsDynamicProxies": "HTTP-sovellusliittymät ja dynaamiset välityspalvelimet", + "HTTPAPIsDynamicProxiesExplanation": "Altista sovelluspalvelut automaattisesti REST-tyylisiksi HTTP-sovellusliittymiksi ja kuluta niitä dynaamisilla JavaScript- ja C # -välityspalvelimilla.", + "CompleteArchitectureInfo": "Moderni arkkitehtuuri ylläpidettävien ohjelmistoratkaisujen luomiseksi.", + "DomainDrivenDesignBasedLayeringModelExplanation": "Auttaa sinua toteuttamaan DDD-pohjaisen kerrostetun arkkitehtuurin ja rakentamaan ylläpidettävän koodipohjan.", + "DomainDrivenDesignBasedLayeringModelExplanationCont": "Tarjoaa käynnistysmalleja, abstrakteja, perusluokkia, palveluja, dokumentaatiota ja oppaita, joiden avulla voit kehittää sovellustasi DDD-mallien ja -periaatteiden perusteella.", + "MicroserviceCompatibleModelExplanation": "Ydinkehys ja esirakennemoduulit on suunniteltu mikropalveluarkkitehtuuria ajatellen.", + "MicroserviceCompatibleModelExplanationCont": "Tarjoaa infrastruktuurin, integraatiot, näytteet ja dokumentaation mikropalveluratkaisujen toteuttamiseksi helpommin, mutta se ei tuo lisää monimutkaisuutta, jos haluat monoliittisen sovelluksen.", + "ModularInfo": "ABP tarjoaa moduulijärjestelmän, jonka avulla voit kehittää uudelleenkäytettäviä sovellusmoduuleja, sitoutua sovelluksen elinkaaren tapahtumiin ja ilmaista riippuvuuksia järjestelmän ydinosien välillä.", + "PreBuiltModulesThemes": "Valmiit moduulit ja teemat", + "PreBuiltModulesThemesExplanation": "Avoimen lähdekoodin ja kaupalliset moduulit ja teemat ovat käyttövalmiita yrityssovelluksessasi.", + "NuGetNPMPackages": "NuGet- ja NPM-paketit", + "NuGetNPMPackagesExplanation": "Jaettu NuGet- ja NPM-paketteina. Helppo asentaa ja päivittää.", + "ExtensibleReplaceable": "Laajennettavissa / vaihdettavissa", + "ExtensibleReplaceableExplanation": "Kaikki palvelut ja moduulit on suunniteltu laajennettavuutta ajatellen. Voit korvata palvelut, sivut, tyylit ja komponentit.", + "CrossCuttingConcernsExplanation2": "Pidä koodipohjasi pienempi, jotta voit keskittyä yritykseesi liittyvään koodiin.", + "CrossCuttingConcernsExplanation3": "Älä lähetä aikaa useiden projektien yhteisten hakemusvaatimusten toteuttamiseen.", + "AuthenticationAuthorization": "Todennus ja valtuutus", + "ExceptionHandling": "Poikkeusten käsittely", + "Validation": "Vahvistus", + "DatabaseConnection": "Tietokantayhteys", + "TransactionManagement": "Tapahtumien hallinta", + "AuditLogging": "Tarkastusten kirjaaminen", + "Caching": "Välimuisti", + "Multitenancy": "Monivärinen", + "DataFiltering": "Tietojen suodatus", + "ConventionOverConfiguration": "Kokoonpanon määritys", + "ConventionOverConfigurationExplanation": "ABP toteuttaa oletusarvoisesti yleiset sovelluskäytännöt minimaalisella tai nolla-kokoonpanolla.", + "ConventionOverConfigurationExplanationList1": "Auto rekisteröi tunnetut palvelut riippuvuusinjektioon.", + "ConventionOverConfigurationExplanationList2": "Paljastaa sovelluspalvelut HTTP-sovellusliittyminä nimeämällä käytäntöjä.", + "ConventionOverConfigurationExplanationList3": "Luo dynaamiset HTTP-asiakasvälityspalvelimet C #: lle ja JavaScriptille.", + "ConventionOverConfigurationExplanationList4": "Tarjoaa oletusvarastoja yhteisöillesi.", + "ConventionOverConfigurationExplanationList5": "Hallitsee työyksikköä verkkopyynnön tai sovelluspalvelumenetelmän mukaan.", + "ConventionOverConfigurationExplanationList6": "Julkaisee luoda, päivittää ja poistaa tapahtumia yhteisöillesi.", + "BaseClasses": "Perusluokat", + "BaseClassesExplanation": "Valmiiksi rakennettu perusluokka yleisiä sovelluskuvioita varten.", + "DeveloperFocusedExplanation": "ABP on kehittäjille.", + "DeveloperFocusedExplanationCont": "Sen tarkoituksena on yksinkertaistaa päivittäistä ohjelmistokehitystäsi samalla, kun se ei estä sinua kirjoittamasta matalan tason koodia.", + "SeeAllFeatures": "Katso kaikki ominaisuudet", + "CLI_CommandLineInterface": "CLI (komentoriviliitäntä)", + "CLI_CommandLineInterfaceExplanation": "Sisältää CLI: n, jonka avulla voit automatisoida uusien projektien luomisen ja uusien moduulien lisäämisen.", + "StartupTemplates": "Käynnistysmallit", + "StartupTemplatesExplanation": "Erilaiset käynnistysmallit tarjoavat täysin määritetyn ratkaisun kehityksen aloittamiseksi.", + "BasedOnFamiliarTools": "Perustuu tuttuihin työkaluihin", + "BasedOnFamiliarToolsExplanation": "Rakennettu ja integroitu jo tunnettujen suosittujen työkalujen kanssa. Matala oppimiskäyrä, helppo sopeutuminen, mukava kehitys.", + "ORMIndependent": "ORM riippumaton", + "ORMIndependentExplanation": "Ydinkehys on ORM / tietokannasta riippumaton ja voi toimia minkä tahansa tietolähteen kanssa. Entity Framework Core- ja MongoDB-palveluntarjoajat ovat jo saatavilla.", + "Features": "Tutustu ABP-kehyksen ominaisuuksiin", + "ABPCLI": "ABP CLI", + "Modularity": "Modulaarisuus", + "BootstrapTagHelpers": "Bootstrap Tag Helpers", + "DynamicForms": "Dynaamiset lomakkeet", + "BundlingMinification": "Niputtaminen ja minimointi", + "BackgroundJobs": "Taustatyöt", + "BackgroundJobsExplanation": "Määritä yksinkertaiset luokat taustalla olevien töiden suorittamiseksi jonossa. Käytä sisäänrakennettua työnhallintaa tai integroi oma. Hangfire ja RabbitMQ -integraatiot ovat jo käytettävissä.", + "DDDInfrastructure": "DDD-infrastruktuuri", + "DomainDrivenDesignInfrastructure": "Toimialueohjattu suunnittelun infrastruktuuri", + "AutoRESTAPIs": "Auto REST -sovellusliittymät", + "DynamicClientProxies": "Dynaamiset asiakaskohtaiset välityspalvelimet", + "DistributedEventBus": "Hajautettu tapahtumabussi", + "DistributedEventBusWithRabbitMQIntegration": "Hajautettu tapahtumaväylä RabbitMQ-integraatiolla", + "TestInfrastructure": "Testaa infrastruktuuri", + "AuditLoggingEntityHistories": "Tarkastusloki ja entiteettihistoria", + "ObjectToObjectMapping": "Object to Object Mapping", + "ObjectToObjectMappingExplanation": " Objektin kartoitus abstraktio AutoMapper-integraatiolla.", + "EmailSMSAbstractions": "Sähköposti ja tekstiviestit", + "EmailSMSAbstractionsWithTemplatingSupport": "Sähköposti- ja SMS-abstraktit mallintamistuen avulla", + "Localization": "Lokalisointi", + "SettingManagement": "Asetusten hallinta", + "ExtensionMethods": "Laajennusmenetelmät", + "ExtensionMethodsHelpers": "Laajennusmenetelmät ja auttajat", + "AspectOrientedProgramming": "Aspektiorientoitu ohjelmointi", + "DependencyInjection": "Riippuvuuden injektio", + "DependencyInjectionByConventions": "Riippuvuuden injektio yleissopimusten mukaan", + "ABPCLIExplanation": "ABP CLI (Command Line Interface) on komentorivityökalu joidenkin yleisten toimintojen suorittamiseen ABP-pohjaisiin ratkaisuihin.", + "ModularityExplanation": "ABP tarjoaa täydellisen infrastruktuurin omien sovellusmoduulien rakentamiseen. Niillä voi olla entiteettejä, palveluja, tietokantaintegraatioita, sovellusliittymiä, käyttöliittymäkomponentteja ja niin edelleen.", + "MultiTenancyExplanation": "ABP-kehys ei vain tue useiden vuokralaisten sovellusten kehittämistä, vaan tekee koodistasi myös enimmäkseen tietämättömän monivuokralaisesta.", + "MultiTenancyExplanation2": "Voi määrittää automaattisesti nykyisen vuokralaisen, eristää eri vuokralaisten tiedot toisistaan.", + "MultiTenancyExplanation3": "Tukee yhtä tietokantaa, tietokantaa vuokralaista kohti ja hybridi-lähestymistapoja.", + "MultiTenancyExplanation4": "Keskity yrityksesi koodiin ja annat kehyksen hoitamaan monivuokrausta puolestasi.", + "BootstrapTagHelpersExplanation": "Sen sijaan, että kirjoittaisit manuaalisesti uudelleenkäynnistyskomponenttien yksityiskohtia, käytä ABP: n tunnisteita yksinkertaistaaksesi sitä ja hyödyntäksesi älykkäitä ominaisuuksia. Voit ehdottomasti käyttää Bootstrapia milloin tahansa.", + "DynamicFormsExplanation": "Dynaamiset lomake- ja syöttötunnisteiden apurit voivat luoda täydellisen lomakkeen mallina C # -luokasta.", + "AuthenticationAuthorizationExplanation": "ASP.NET Core Identity & IdentityServer4 -palveluun integroidut monipuoliset todennus- ja todennusvaihtoehdot. Tarjoaa laajennettavan ja yksityiskohtaisen lupajärjestelmän.", + "CrossCuttingConcernsExplanation": "Älä toista itseäsi kaikkien näiden yleisten asioiden toteuttamiseksi uudelleen ja uudelleen. Keskity yrityskoodiin ja anna ABP: n automatisoida ne käytäntöjen mukaan.", + "DatabaseConnectionTransactionManagement": "Tietokantayhteys ja tapahtumien hallinta", + "CorrelationIdTracking": "Korrelaatio-Id-seuranta", + "BundlingMinificationExplanation": "ABP tarjoaa yksinkertaisen, dynaamisen, tehokkaan, modulaarisen ja sisäänrakennetun niputus- ja pienentämisjärjestelmän.", + "VirtualFileSystemnExplanation": "Virtuaalinen tiedostojärjestelmä mahdollistaa sellaisten tiedostojen hallinnan, joita ei ole fyysisesti tiedostojärjestelmässä (levyllä). Sitä käytetään pääasiassa upottamaan (js, css, kuva, cshtml ...) tiedostot kokoonpanoiksi ja käyttämään niitä kuin fyysisiä tiedostoja ajon aikana.", + "ThemingExplanation": "Theming-järjestelmän avulla voit kehittää sovellus- ja moduuliteemasi itsenäisesti määrittelemällä joukon yhteisiä peruskirjastoja ja asetteluja uusimman Bootstrap-kehyksen perusteella.", + "DomainDrivenDesignInfrastructureExplanation": "Täydellinen infrastruktuuri kerrostettujen sovellusten rakentamiseen, joka perustuu toimialueohjattuihin suunnittelumalleihin ja periaatteisiin;", + "Specification": "Erittely", + "Repository": "Arkisto", + "DomainService": "Verkkotunnuspalvelu", + "ValueObject": "Arvo-objekti", + "ApplicationService": "Sovelluspalvelu", + "DataTransferObject": "Tiedonsiirtokohde", + "AggregateRootEntity": "Kokonaisjuuri, entiteetti", + "AutoRESTAPIsExplanation": "ABP voi määrittää sovelluspalvelut automaattisesti API-ohjaimiksi sopimuksen mukaan.", + "DynamicClientProxiesExplanation": "Kuluta helposti API: si JavaScript- ja C # -asiakkailta.", + "DistributedEventBusWithRabbitMQIntegrationExplanation": "Julkaise ja kuluta jaettuja tapahtumia helposti käyttämällä sisäänrakennettua hajautettua tapahtumaväylää, jossa on käytettävissä RabbitMQ-integraatio.", + "TestInfrastructureExplanation": "Kehys on kehitetty yksikkö- ja integraatiotestaus ajatellen. Tarjoaa sinulle perusluokkia helpottamaan. Käynnistysmalleissa on valmiiksi konfiguroitu testaus.", + "AuditLoggingEntityHistoriesExplanation": "Sisäänrakennettu tarkastuskirjaus yrityskriittisille sovelluksille. Pyyntö-, palvelu-, menetelmätason tarkastusloki ja entiteettihistoria omaisuuden tason yksityiskohdilla.", + "EmailSMSAbstractionsWithTemplatingSupportExplanation": "IEmailSender- ja ISmsSender-abstraktit erottavat sovelluslogiikkasi infrastruktuurista. Edistyneen sähköpostimallijärjestelmän avulla voit luoda ja lokalisoida sähköpostimalleja ja käyttää niitä helposti tarvittaessa.", + "LocalizationExplanation": "Lokalisointijärjestelmä antaa mahdollisuuden luoda resursseja yksinkertaisiin JSON-tiedostoihin ja käyttää niitä käyttöliittymän lokalisointiin. Se tukee edistyneitä skenaarioita, kuten perintö, laajennukset ja JavaScript-integrointi, samalla kun se on täysin yhteensopiva AspNet Core -järjestelmän lokalisointijärjestelmän kanssa.", + "SettingManagementExplanation": "Määritä sovelluksesi asetukset ja hanki ajonaikaiset arvot nykyisen kokoonpanon, vuokralaisen ja käyttäjän perusteella.", + "ExtensionMethodsHelpersExplanation": "Älä toista itseäsi edes triviaalien koodiosien suhteen. Vakiotyyppien laajennukset ja apuvälineet tekevät koodistasi paljon puhtaamman ja helpommin kirjoitettavan.", + "AspectOrientedProgrammingExplanation": "Tarjoaa mukavan infrastruktuurin dynaamisten valtakirjojen luomiseen ja Aspect Oriented Programming -toiminnon toteuttamiseen. Kuuntele mikä tahansa luokka ja suorita koodisi ennen ja jälkeen jokaisen menetelmän suorituksen.", + "DependencyInjectionByConventionsExplanation": "Luokat ei tarvitse rekisteröidä riippuvuusinjektioon manuaalisesti. Rekisteröi yleiset palvelutyypit sopimuksen mukaan automaattisesti. Muun tyyppisissä palveluissa voit käyttää käyttöliittymiä ja määritteitä sen helpottamiseksi ja paikoillaan.", + "DataFilteringExplanation": "Määritä ja käytä tietosuodattimia, joita käytetään automaattisesti, kun kysyt entiteettejä tietokannasta. Pehmeä poisto- ja MultiTenant-suodattimet toimitetaan heti, kun otat käyttöön yksinkertaiset käyttöliittymät.", + "PublishEvents": "Julkaise tapahtumia", + "HandleEvents": "Käsittele tapahtumia", + "AndMore": "ja enemmän...", + "Code": "Koodi", + "Result": "Tulos", + "SeeTheDocumentForMoreInformation": "Katso lisätietoja {0} asiakirjasta ", + "IndexPageHeroSection": " avoin lähdekoodi verkkosovellus
Framework
asp.net-ytimelle ", + "UiFramework": "Käyttöliittymäkehys", + "EmailAddress": "Sähköpostiosoite", + "Mobile": "Matkapuhelin", + "ReactNative": "Reagoi Native", + "Strong": "Vahva", + "Complete": "Saattaa loppuun", + "BasedLayeringModel": "Perustuva kerrosmalli", + "Microservice": "Mikropalvelu", + "Compatible": "Yhteensopiva", + "MeeTTheABPCommunityInfo": "Tavoitteenamme on luoda ympäristö, jossa kehittäjät voivat auttaa toisiaan artikkeleilla, oppailla, tapaustutkimuksilla jne. Ja tavata samanmielisiä ihmisiä.", + "JoinTheABPCommunityInfo": "Ole mukana elävässä yhteisössä ja tule osallistujana sivutuotteiden kehykseen!", + "AllArticles": "Kaikki artikkelit", + "SubmitYourArticle": "Lähetä artikkelisi", + "DynamicClientProxyDocument": "Katso dynaamisen asiakkaan välityspalvelimen dokumentaatiot JavaScriptille ja C # .", + "EmailSMSAbstractionsDocument": "Katso lisätietoja sähköpostitse ja tekstiviestien lähettäminen -asiakirjoista.", + "CreateProjectWizard": "Tämä ohjattu toiminto luo uuden projektin käynnistysmallista, joka on määritetty oikein aloittamaan projekti.", + "TieredOption": "Luo porrastetun ratkaisun, jossa Web- ja Http-API-kerrokset erotetaan fyysisesti. Jos sitä ei ole valittu, luodaan kerrostettu ratkaisu, joka on vähemmän monimutkainen ja sopii useimpiin tilanteisiin.", + "SeparateIdentityServerOption": "Erottaa palvelinpuolen kahteen sovellukseen: Ensimmäinen on identiteettipalvelimelle ja toinen palvelinpuolen HTTP-sovellusliittymälle.", + "UseslatestPreVersion": "Käyttää uusinta julkaisua edeltävää versiota", + "ReadTheDocumentation": " Lue Dokumentaatio ", + "Documentation": "Dokumentointi", + "GettingStartedTutorial": "Aloitusopas", + "ApplicationDevelopmentTutorial": "Sovelluskehitysopastus", + "TheStartupTemplate": "Käynnistysmalli", + "InstallABPCLIInfo": "ABP CLI on nopein tapa aloittaa uusi ratkaisu ABP-kehyksellä. Asenna ABP CLI komentorivillä:", + "DifferentLevelOfNamespaces": "Voit käyttää eri nimiavaruustasoja; esimerkiksi. BookStore, Acme.BookStore tai Acme.Retail.BookStore.", + "ABPCLIExamplesInfo": " Uusi -komento luo kerrostetun MVC-sovelluksen , jonka tietokannan tarjoaja on Entity Framework Core . Sillä on kuitenkin muita vaihtoehtoja. Esimerkkejä:", + "SeeCliDocumentForMoreInformation": "Katso lisää vaihtoehtoja ABP CLI -asiakirjasta tai valitse yllä Suora lataus -välilehti.", + "Optional": "Valinnainen", + "LocalFrameworkRef": "Säilytä kehyspakettien paikalliset projektiviitteet.", + "BlobStoring": "BLOB-tallennus", + "BlobStoringExplanation": "BLOB-tallennusjärjestelmä tarjoaa abstraktin BLOBien kanssa työskentelemiseen. ABP tarjoaa joitain valmiita tallennuspalveluntarjoajan integraatioita (Azure, AWS, tiedostojärjestelmä, tietokanta jne.), Joita voit helposti käyttää sovelluksissasi.", + "TextTemplating": "Tekstin mallintaminen", + "TextTemplatingExplanation": "Tekstimallia käytetään sisällön renderointiin dynaamisesti mallin ja mallin (dataobjektin) perusteella. Voit käyttää sitä esimerkiksi dynaamisen sähköpostisisällön luomiseen valmiilla mallilla.", + "MultipleUIOptions": "Useita käyttöliittymävaihtoehtoja", + "MultipleDBOptions": "Useita tietokantapalveluja", + "MultipleUIOptionsExplanation": "Ydinkehys on suunniteltu käyttöliittymästä riippumattomaksi ja se voi toimia minkä tahansa tyyppisen käyttöliittymäjärjestelmän kanssa, kun taas useita valmiiksi rakennettuja ja integroituja vaihtoehtoja toimitetaan heti.", + "MultipleDBOptionsExplanation": "Kehys voi toimia minkä tahansa tietolähteen kanssa, kun taas seuraavat palveluntarjoajat on virallisesti kehitetty ja tuettu;", + "SelectLanguage": "Valitse kieli", + "LatestArticleOnCommunity": "Viimeisin artikkeli ABP-yhteisöstä", + "Register": "Rekisteröidy", + "IsDownloadable": "On ladattavissa" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json new file mode 100644 index 0000000000..878af5e830 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json @@ -0,0 +1,202 @@ +{ + "culture": "fr", + "texts": { + "GetStarted": "Commencer - Modèles de démarrage", + "Create": "Créer", + "NewProject": "Nouveau projet", + "DirectDownload": "Téléchargement direct", + "ProjectName": "Nom du projet", + "ProjectType": "Type de projet", + "DatabaseProvider": "Fournisseur de base de données", + "DatabaseManagementSystem": "Système de gestion de base de données", + "NTier": "N-Tier", + "IncludeUserInterface": "Inclure l'interface utilisateur", + "CreateNow": "Créer maintenant", + "TheStartupProject": "Le projet de démarrage", + "Tutorial": "Didacticiel", + "UsingCLI": "Utilisation de la CLI", + "SeeDetails": "Voir les détails", + "AbpShortDescription": "ABP Framework est une infrastructure complète pour créer des applications Web modernes en suivant les meilleures pratiques et conventions de développement logiciel.", + "SourceCodeUpper": "CODE SOURCE", + "LatestReleaseLogs": "Derniers journaux de version", + "Infrastructure": "Infrastructure", + "Architecture": "Architecture", + "Modular": "Modulaire", + "DontRepeatYourself": "Ne vous répétez pas", + "DeveloperFocused": "Axé sur les développeurs", + "FullStackApplicationInfrastructure": "Infrastructure d'application complète.", + "DomainDrivenDesign": "Conception pilotée par le domaine", + "DomainDrivenDesignExplanation": "Conçu et développé sur la base des modèles et principes DDD. Fournit un modèle en couches pour votre application.", + "Authorization": "Autorisation", + "AuthorizationExplanation": "Autorisation avancée avec utilisateur, rôle et système d'autorisation précis. Construit sur la bibliothèque d'identité Microsoft.", + "MultiTenancy": "Locations multiples", + "MultiTenancyExplanationShort": "Les applications SaaS simplifiées! Multi-location intégrée de la base de données à l'interface utilisateur.", + "CrossCuttingConcerns": "Préoccupations transversales", + "CrossCuttingConcernsExplanationShort": "Infrastructure complète pour l'autorisation, la validation, la gestion des exceptions, la mise en cache, la journalisation d'audit, la gestion des transactions et plus encore.", + "BuiltInBundlingMinification": "Regroupement et minification intégrés", + "BuiltInBundlingMinificationExplanation": "Pas besoin d'utiliser des outils externes pour le regroupement et la minimisation. ABP offre un moyen plus simple, dynamique, puissant, modulaire et intégré!", + "VirtualFileSystem": "Système de fichiers virtuel", + "VirtualFileSystemExplanation": "Incorporez des vues, des scripts, des styles, des images ... dans des packages / bibliothèques et réutilisez-les dans différentes applications.", + "Theming": "Thème", + "ThemingExplanationShort": "Utilisez et personnalisez le thème d'interface utilisateur standard basé sur le bootstrap ou créez le vôtre.", + "BootstrapTagHelpersDynamicForms": "Aide aux balises Bootstrap et formulaires dynamiques", + "BootstrapTagHelpersDynamicFormsExplanation": "Au lieu d'écrire manuellement les détails répétitifs des composants d'amorçage, utilisez les assistants de balises d'ABP pour le simplifier et tirer parti d'intellisense. Créez rapidement des formulaires d'interface utilisateur basés sur un modèle C # à l'aide de l'assistant de balise de formulaire dynamique.", + "HTTPAPIsDynamicProxies": "API HTTP et proxys dynamiques", + "HTTPAPIsDynamicProxiesExplanation": "Exposez automatiquement les services d'application en tant qu'API HTTP de style REST et utilisez-les avec des proxys JavaScript et C# dynamiques.", + "CompleteArchitectureInfo": "Architecture moderne pour créer des solutions logicielles maintenables.", + "DomainDrivenDesignBasedLayeringModelExplanation": "Vous aide à implémenter une architecture en couches basée sur DDD et à créer une base de code maintenable.", + "DomainDrivenDesignBasedLayeringModelExplanationCont": "Fournit des modèles de démarrage, des abstractions, des classes de base, des services, de la documentation et des guides pour vous aider à développer votre application basée sur les modèles et principes DDD.", + "MicroserviceCompatibleModelExplanation": "Le framework de base et les modules de pré-construction sont conçus avec l'architecture de microservice à l'esprit.", + "MicroserviceCompatibleModelExplanationCont": "Fournit une infrastructure, des intégrations, des exemples et de la documentation pour mettre en œuvre des solutions de microservices plus facilement, sans apporter de complexité supplémentaire si vous souhaitez une application monolithique.", + "ModularInfo": "ABP fournit un système de modules qui vous permet de développer des modules d'application réutilisables, de les relier aux événements du cycle de vie des applications et d'exprimer les dépendances entre les parties centrales de votre système.", + "PreBuiltModulesThemes": "Modules et thèmes prédéfinis", + "PreBuiltModulesThemesExplanation": "Les modules et thèmes open source et commerciaux sont prêts à être utilisés dans votre application professionnelle.", + "NuGetNPMPackages": "Packages NuGet et NPM", + "NuGetNPMPackagesExplanation": "Distribué sous forme de packages NuGet et NPM. Facile à installer et à mettre à jour.", + "ExtensibleReplaceable": "Extensible / remplaçable", + "ExtensibleReplaceableExplanation": "Tous les services et modules sont conçus pour l'extensibilité. Vous pouvez remplacer des services, des pages, des styles et des composants.", + "CrossCuttingConcernsExplanation2": "Réduisez la taille de votre base de code afin de rester concentré sur le code spécifique à votre entreprise.", + "CrossCuttingConcernsExplanation3": "N'envoyez pas de temps pour mettre en œuvre les exigences d'application communes sur plusieurs projets.", + "AuthenticationAuthorization": "Autorisation d'authentification", + "ExceptionHandling": "Gestion des exceptions", + "Validation": "Validation", + "DatabaseConnection": "Connexion à la base de données", + "TransactionManagement": "Gestion des transactions", + "AuditLogging": "Journalisation d'audit", + "Caching": "Mise en cache", + "Multitenancy": "Multi-souscrivants", + "DataFiltering": "Filtrage des données", + "ConventionOverConfiguration": "Convention plutôt que configuration", + "ConventionOverConfigurationExplanation": "ABP implémente par défaut des conventions d'application communes avec une configuration minimale ou nulle.", + "ConventionOverConfigurationExplanationList1": "Enregistre automatiquement les services connus pour l'injection de dépendances.", + "ConventionOverConfigurationExplanationList2": "Expose les services d'application en tant qu'API HTTP par des conventions de dénomination.", + "ConventionOverConfigurationExplanationList3": "Crée des proxys client HTTP dynamiques pour C# et JavaScript.", + "ConventionOverConfigurationExplanationList4": "Fournit des référentiels par défaut pour vos entités.", + "ConventionOverConfigurationExplanationList5": "Gère l'unité de travail par demande Web ou méthode de service d'application.", + "ConventionOverConfigurationExplanationList6": "Publie des événements de création, de mise à jour et de suppression pour vos entités.", + "BaseClasses": "Classes de base", + "BaseClassesExplanation": "Classes de base prédéfinies pour les modèles d'application courants.", + "DeveloperFocusedExplanation": "ABP est destiné aux développeurs.", + "DeveloperFocusedExplanationCont": "Il vise à simplifier votre développement logiciel quotidien sans vous empêcher d'écrire du code de bas niveau.", + "SeeAllFeatures": "Voir toutes les fonctionnalités", + "CLI_CommandLineInterface": "CLI (interface de ligne de commande)", + "CLI_CommandLineInterfaceExplanation": "Inclut une CLI pour vous aider à automatiser la création de nouveaux projets et l'ajout de nouveaux modules.", + "StartupTemplates": "Modèles de démarrage", + "StartupTemplatesExplanation": "Divers modèles de démarrage fournissent une solution entièrement configurée pour démarrer rapidement votre développement.", + "BasedOnFamiliarTools": "Basé sur des outils familiers", + "BasedOnFamiliarToolsExplanation": "Construit sur et intégré avec des outils populaires que vous connaissez déjà. Faible courbe d'apprentissage, adaptation facile, développement confortable.", + "ORMIndependent": "ORM indépendant", + "ORMIndependentExplanation": "Le framework de base est indépendant de l'ORM / de la base de données et peut fonctionner avec n'importe quelle source de données. Les fournisseurs Entity Framework Core et MongoDB sont déjà disponibles.", + "Features": "Explorez les fonctionnalités du framework ABP", + "ABPCLI": "CLI ABP", + "Modularity": "Modularité", + "BootstrapTagHelpers": "Assistants de balises Bootstrap", + "DynamicForms": "Formulaires dynamiques", + "BundlingMinification": "Regroupement et minification", + "BackgroundJobs": "Emplois d'arrière-plan", + "BackgroundJobsExplanation": "Définissez des classes simples pour exécuter les travaux en arrière-plan comme mis en file d'attente. Utilisez le gestionnaire de tâches intégré ou intégrez le vôtre. Les intégrations Hangfire et RabbitMQ sont déjà disponibles.", + "DDDInfrastructure": "Infrastructure DDD", + "DomainDrivenDesignInfrastructure": "Infrastructure Domain Driven Design", + "AutoRESTAPIs": "API REST automatiques", + "DynamicClientProxies": "Proxys clients dynamiques", + "DistributedEventBus": "Bus d'événements distribués", + "DistributedEventBusWithRabbitMQIntegration": "Bus d'événements distribués avec intégration RabbitMQ", + "TestInfrastructure": "Infrastructure de test", + "AuditLoggingEntityHistories": "Journalisation d'audit et historiques d'entités", + "ObjectToObjectMapping": "Mappage d'objet à objet", + "ObjectToObjectMappingExplanation": " Mappage objet à objet abstraction avec intégration AutoMapper.", + "EmailSMSAbstractions": "Abstractions par e-mail et SMS", + "EmailSMSAbstractionsWithTemplatingSupport": "Abstractions par e-mail et SMS avec prise en charge de la création de modèles", + "Localization": "Localisation", + "SettingManagement": "Gestion des paramètres", + "ExtensionMethods": "Méthodes d'extension", + "ExtensionMethodsHelpers": "Méthodes d'extension et aides", + "AspectOrientedProgramming": "Programmation orientée aspect", + "DependencyInjection": "Injection de dépendance", + "DependencyInjectionByConventions": "Injection de dépendances par conventions", + "ABPCLIExplanation": "ABP CLI (Command Line Interface) est un outil de ligne de commande pour effectuer certaines opérations courantes pour les solutions basées sur ABP.", + "ModularityExplanation": "ABP fournit une infrastructure complète pour créer vos propres modules d'application qui peuvent avoir des entités, des services, une intégration de base de données, des API, des composants d'interface utilisateur, etc.", + "MultiTenancyExplanation": "Le framework ABP prend non seulement en charge le développement d'applications multi-souscrivants, mais rend également votre code pratiquement inconscient de la multi-location.", + "MultiTenancyExplanation2": "Peut déterminer automatiquement le souscrivant actuel, isoler les données de différents locataires les uns des autres.", + "MultiTenancyExplanation3": "Prend en charge une base de données unique, une base de données par souscrivant et des approches hybrides.", + "MultiTenancyExplanation4": "Vous vous concentrez sur votre code métier et laissez le framework gérer la multi-souscrivants en votre nom.", + "BootstrapTagHelpersExplanation": "Au lieu d'écrire manuellement les détails répétitifs des composants Boostrap, utilisez les aides de balises d'ABP pour le simplifier et tirer parti d'intellisense. Vous pouvez certainement utiliser Bootstrap chaque fois que vous en avez besoin.", + "DynamicFormsExplanation": "Les assistants dynamiques de formulaire et de balise d'entrée peuvent créer le formulaire complet à partir d'une classe C# comme modèle.", + "AuthenticationAuthorizationExplanation": "Options d'authentification et d'autorisation riches intégrées à ASP.NET Core Identity & IdentityServer4. Fournit un système d'autorisation extensible et détaillé.", + "CrossCuttingConcernsExplanation": "Ne vous répétez pas pour mettre en œuvre toutes ces choses courantes encore et encore. Concentrez-vous sur votre code métier et laissez ABP les automatiser par des conventions.", + "DatabaseConnectionTransactionManagement": "Connexion à la base de données et gestion des transactions", + "CorrelationIdTracking": "Suivi des identifiants de corrélation", + "BundlingMinificationExplanation": "ABP offre un système de regroupement et de minification simple, dynamique, puissant, modulaire et intégré.", + "VirtualFileSystemnExplanation": "Le système de fichiers virtuel permet de gérer des fichiers qui n'existent pas physiquement sur le système de fichiers (disque). Il est principalement utilisé pour incorporer des fichiers (js, css, image, cshtml ...) dans des assemblys et les utiliser comme des fichiers physiques lors de l'exécution.", + "ThemingExplanation": "Le système de thématisation permet de développer votre application et vos modules indépendamment du thème en définissant un ensemble de bibliothèques et de mises en page de base communes, basées sur le dernier framework Bootstrap.", + "DomainDrivenDesignInfrastructureExplanation": "Une infrastructure complète pour créer des applications en couches basées sur les modèles et principes de conception pilotée par domaine;", + "Specification": "spécification", + "Repository": "Dépôt", + "DomainService": "Service de domaine", + "ValueObject": "Objet de valeur", + "ApplicationService": "Service d'application", + "DataTransferObject": "Objet de transfert de données", + "AggregateRootEntity": "Racine agrégée, entité", + "AutoRESTAPIsExplanation": "ABP peut configurer automatiquement vos services d'application en tant que contrôleurs d'API par convention.", + "DynamicClientProxiesExplanation": "Utilisez facilement vos API à partir de clients JavaScript et C#.", + "DistributedEventBusWithRabbitMQIntegrationExplanation": "Publiez et consommez facilement des événements distribués à l'aide du bus d'événements distribués intégré avec l'intégration RabbitMQ disponible.", + "TestInfrastructureExplanation": "Le framework a été développé en pensant aux tests unitaires et d'intégration. Vous fournit des classes de base pour vous faciliter la tâche. Les modèles de démarrage sont pré-configurés pour les tests.", + "AuditLoggingEntityHistoriesExplanation": "Journalisation d'audit intégrée pour les applications stratégiques. Requête, service, journalisation d'audit au niveau de la méthode et historiques d'entités avec des détails au niveau de la propriété.", + "EmailSMSAbstractionsWithTemplatingSupportExplanation": "Les abstractions IEmailSender et ISmsSender découpent la logique de votre application de l'infrastructure. Le système de modèle de courrier électronique avancé permet de créer et de localiser des modèles de courrier électronique et de les utiliser facilement en cas de besoin.", + "LocalizationExplanation": "Le système de localisation permet de créer des ressources dans des fichiers JSON simples et de les utiliser pour localiser votre interface utilisateur. Il prend en charge des scénarios avancés tels que l'héritage, les extensions et l'intégration JavaScript tout en étant entièrement compatible avec le système de localisation d'AspNet Core.", + "SettingManagementExplanation": "Définissez les paramètres de votre application et obtenez des valeurs à l'exécution en fonction de la configuration, du locataire et de l'utilisateur actuels.", + "ExtensionMethodsHelpersExplanation": "Ne vous répétez pas même pour des parties de code triviales. Les extensions et aides pour les types standard rendent votre code beaucoup plus propre et facile à écrire.", + "AspectOrientedProgrammingExplanation": "Fournit une infrastructure confortable pour créer des proxys dynamiques et mettre en œuvre la programmation orientée aspect. Interceptez n'importe quelle classe et exécutez votre code avant et après chaque exécution de méthode.", + "DependencyInjectionByConventionsExplanation": "Inutile d'inscrire manuellement vos classes à l'injection de dépendances. Enregistre automatiquement les types de services courants par convention. Pour les autres types de services, vous pouvez utiliser des interfaces et des attributs pour le rendre plus simple et sur place.", + "DataFilteringExplanation": "Définissez et utilisez des filtres de données qui sont automatiquement appliqués lorsque vous interrogez des entités de la base de données. Les filtres Soft Delete et MultiTenant sont fournis par défaut lorsque vous implémentez des interfaces simples.", + "PublishEvents": "Publier des événements", + "HandleEvents": "Gérer les événements", + "AndMore": "et plus...", + "Code": "Code", + "Result": "Résultat", + "SeeTheDocumentForMoreInformation": "Consultez le {0} document pour plus d'informations", + "IndexPageHeroSection": " open source Application Web
Framework
pour asp.net core ", + "UiFramework": "Framework de l'interface utilisateur", + "EmailAddress": "Adresse e-mail", + "Mobile": "Mobile", + "ReactNative": "Réagir natif", + "Strong": "Fort", + "Complete": "Compléter", + "BasedLayeringModel": "Modèle basé sur des couches", + "Microservice": "Microservice", + "Compatible": "Compatible", + "MeeTTheABPCommunityInfo": "Notre mission est de créer un environnement où les développeurs peuvent s'entraider avec des articles, des tutoriels, des études de cas, etc. et rencontrer des personnes partageant les mêmes idées.", + "JoinTheABPCommunityInfo": "Impliquez-vous dans une communauté dynamique et devenez un contributeur au cadre ABP!", + "AllArticles": "Tous les articles", + "SubmitYourArticle": "Soumettez votre article", + "DynamicClientProxyDocument": "Consultez les documentations sur le proxy client dynamique pour JavaScript et C # .", + "EmailSMSAbstractionsDocument": "Consultez les documents e-mail et Envoi de SMS pour plus d'informations.", + "CreateProjectWizard": "Cet assistant crée un nouveau projet à partir du modèle de démarrage qui est correctement configuré pour démarrer rapidement votre projet.", + "TieredOption": "Crée une solution à plusieurs niveaux dans laquelle les couches API Web et Http sont physiquement séparées. Si elle n'est pas cochée, crée une solution en couches qui est moins complexe et adaptée à la plupart des scénarios.", + "SeparateIdentityServerOption": "Sépare le côté serveur en deux applications: la première est pour le serveur d'identité et la seconde pour votre API HTTP côté serveur.", + "UseslatestPreVersion": "Utilise la dernière version préliminaire", + "ReadTheDocumentation": " Lire La documentation ", + "Documentation": "Documentation", + "GettingStartedTutorial": "Tutoriel de mise en route", + "ApplicationDevelopmentTutorial": "Tutoriel de développement d'applications", + "TheStartupTemplate": "Le modèle de démarrage", + "InstallABPCLIInfo": "ABP CLI est le moyen le plus rapide de démarrer une nouvelle solution avec le framework ABP. Installez l'interface de ligne de commande ABP à l'aide d'une fenêtre de ligne de commande:", + "DifferentLevelOfNamespaces": "Vous pouvez utiliser différents niveaux d'espaces de noms; par exemple. BookStore, Acme.BookStore ou Acme.Retail.BookStore.", + "ABPCLIExamplesInfo": "La commande nouvelle crée une application MVC en couches avec Entity Framework Core comme fournisseur de base de données. Cependant, il a des options supplémentaires. Exemples:", + "SeeCliDocumentForMoreInformation": "Consultez le document ABP CLI pour plus d'options ou sélectionnez l'onglet \"Téléchargement direct\" ci-dessus.", + "Optional": "Optionnel", + "LocalFrameworkRef": "Conservez la référence de projet locale pour les packages de structure.", + "BlobStoring": "Stockage BLOB", + "BlobStoringExplanation": "Le système de stockage BLOB fournit une abstraction pour travailler avec les BLOB. ABP fournit des intégrations de fournisseur de stockage prédéfinies (Azure, AWS, système de fichiers, base de données, etc.) que vous pouvez facilement utiliser dans vos applications.", + "TextTemplating": "Création de modèles de texte", + "TextTemplatingExplanation": "La création de modèles de texte est utilisée pour rendre le contenu de manière dynamique en fonction d'un modèle et d'un modèle (un objet de données). Par exemple, vous pouvez l'utiliser pour créer des contenus d'e-mail dynamiques avec un modèle prédéfini.", + "MultipleUIOptions": "Options d'interface utilisateur multiples", + "MultipleDBOptions": "Fournisseurs de bases de données multiples", + "MultipleUIOptionsExplanation": "Le framework de base est conçu comme indépendant de l'interface utilisateur et peut fonctionner avec tout type de système d'interface utilisateur, tandis que plusieurs options prédéfinies et intégrées sont fournies prêtes à l'emploi.", + "MultipleDBOptionsExplanation": "Le framework peut fonctionner avec n'importe quelle source de données, tandis que les fournisseurs suivants sont officiellement développés et pris en charge;", + "SelectLanguage": "Choisir la langue", + "LatestArticleOnCommunity": "Dernier article sur la communauté ABP", + "Register": "S'inscrire", + "IsDownloadable": "Est téléchargeable" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json new file mode 100644 index 0000000000..a7974d8658 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json @@ -0,0 +1,202 @@ +{ + "culture": "hi", + "texts": { + "GetStarted": "प्रारंभ करें - स्टार्टअप टेम्पलेट", + "Create": "सृजन करना", + "NewProject": "नया काम", + "DirectDownload": "प्रत्यक्षत: डाउनलोड", + "ProjectName": "परियोजना का नाम", + "ProjectType": "प्रोजेक्ट का प्रकार", + "DatabaseProvider": "डेटाबेस प्रदाता", + "DatabaseManagementSystem": "डेटाबेस प्रबंधन प्रणाली", + "NTier": "n स्तरीय", + "IncludeUserInterface": "उपयोगकर्ता इंटरफ़ेस शामिल करें", + "CreateNow": "अब बनाओ", + "TheStartupProject": "स्टार्टअप प्रोजेक्ट", + "Tutorial": "ट्यूटोरियल", + "UsingCLI": "सीएलआई का उपयोग करना", + "SeeDetails": "विवरण देखें", + "AbpShortDescription": "एबीपी फ्रेमवर्क सॉफ्टवेयर विकास सर्वोत्तम प्रथाओं और सम्मेलनों का पालन करके आधुनिक वेब एप्लिकेशन बनाने के लिए एक पूर्ण बुनियादी ढांचा है।", + "SourceCodeUpper": "सोर्स कोड", + "LatestReleaseLogs": "नवीनतम रिलीज़ लॉग", + "Infrastructure": "भूमिकारूप व्यवस्था", + "Architecture": "आर्किटेक्चर", + "Modular": "मॉड्यूलर", + "DontRepeatYourself": "खुद को दोहराएं नहीं", + "DeveloperFocused": "डेवलपर ने फोकस किया", + "FullStackApplicationInfrastructure": "पूर्ण स्टैक अनुप्रयोग अवसंरचना।", + "DomainDrivenDesign": "डोमेन संचालित डिजाइन", + "DomainDrivenDesignExplanation": "डीडीडी पैटर्न और सिद्धांतों के आधार पर डिजाइन और विकसित। आपके आवेदन के लिए एक स्तरित मॉडल प्रदान करता है।", + "Authorization": "प्राधिकार", + "AuthorizationExplanation": "उपयोगकर्ता, भूमिका और ठीक-ठीक अनुमति प्रणाली के साथ उन्नत प्राधिकरण। Microsoft पहचान लाइब्रेरी पर बनाया गया।", + "MultiTenancy": "बहु किरायेदारी", + "MultiTenancyExplanationShort": "सास अनुप्रयोगों आसान बना दिया! यूआई के लिए डेटाबेस से एकीकृत मल्टी-टेनेंसी।", + "CrossCuttingConcerns": "फिल्म आदि में दृश्यों के संपादन संबंधी चिंताएं", + "CrossCuttingConcernsExplanationShort": "प्राधिकरण, सत्यापन, अपवाद से निपटने, कैशिंग, ऑडिट लॉगिंग, लेनदेन प्रबंधन और बहुत कुछ के लिए पूरा बुनियादी ढांचा।", + "BuiltInBundlingMinification": "अंतर्निहित बंडलिंग और न्यूनतम", + "BuiltInBundlingMinificationExplanation": "बंडलिंग और लघुकरण के लिए बाहरी उपकरणों का उपयोग करने की आवश्यकता नहीं है। ABP एक सरल, गतिशील, शक्तिशाली, मॉड्यूलर और बिल्ट-इन तरीका प्रदान करता है!", + "VirtualFileSystem": "वर्चुअल फाइल सिस्टम", + "VirtualFileSystemExplanation": "पैकेज, पुस्तकालयों में विचार, स्क्रिप्ट, शैली, चित्र एम्बेड करें और विभिन्न अनुप्रयोगों में उनका पुन: उपयोग करें।", + "Theming": "थीम", + "ThemingExplanationShort": "बूटस्ट्रैप-आधारित मानक UI थीम का उपयोग करें और अनुकूलित करें या अपना स्वयं का बनाएं।", + "BootstrapTagHelpersDynamicForms": "बूटस्ट्रैप टैग हेल्पर्स और डायनामिक फॉर्म", + "BootstrapTagHelpersDynamicFormsExplanation": "बूटस्ट्रैप घटकों के दोहराए गए विवरणों को मैन्युअल रूप से लिखने के बजाय, इसे सरल बनाने और अंतरंगता का लाभ उठाने के लिए एबीपी के टैग सहायकों का उपयोग करें। डायनामिक फॉर्म टैग हेल्पर का उपयोग करके C # मॉडल के आधार पर जल्दी से UI फॉर्म का निर्माण करें।", + "HTTPAPIsDynamicProxies": "HTTP एपीआई और डायनेमिक प्रॉक्सी", + "HTTPAPIsDynamicProxiesExplanation": "REST शैली HTTP API के रूप में एप्लिकेशन सेवाओं को स्वचालित रूप से उजागर करें, और उन्हें गतिशील जावास्क्रिप्ट और C # प्रॉक्सी के साथ उपभोग करें।", + "CompleteArchitectureInfo": "बनाए रखने योग्य सॉफ़्टवेयर समाधान बनाने के लिए आधुनिक वास्तुकला।", + "DomainDrivenDesignBasedLayeringModelExplanation": "डीडीडी आधारित स्तरित वास्तुकला को लागू करने और बनाए रखने योग्य कोड आधार बनाने में आपकी सहायता करता है।", + "DomainDrivenDesignBasedLayeringModelExplanationCont": "DDD पैटर्न और सिद्धांतों के आधार पर आपके एप्लिकेशन को विकसित करने में मदद करने के लिए स्टार्टअप टेम्प्लेट, सार, आधार कक्षाएं, सेवाएं, प्रलेखन और मार्गदर्शिका प्रदान करता है।", + "MicroserviceCompatibleModelExplanation": "कोर फ्रेमवर्क और प्री-बिल्ड मॉड्यूल को दिमाग में माइक्रोसैस आर्किटेक्चर के साथ डिजाइन किया गया है।", + "MicroserviceCompatibleModelExplanationCont": "यदि आप एक अखंड आवेदन चाहते हैं, तो यह आसान नहीं है कि माइक्रोसॉफ़्ट समाधानों को लागू करने के लिए बुनियादी ढाँचा, एकीकरण, नमूने और प्रलेखन प्रदान करता है।", + "ModularInfo": "एबीपी एक मॉड्यूल प्रणाली प्रदान करता है जो आपको पुन: प्रयोज्य एप्लिकेशन मॉड्यूल विकसित करने, एप्लिकेशन जीवन चक्र घटनाओं में टाई करने और आपके सिस्टम के मुख्य भागों के बीच निर्भरता व्यक्त करने की अनुमति देता है।", + "PreBuiltModulesThemes": "पूर्व निर्मित मॉड्यूल और थीम", + "PreBuiltModulesThemesExplanation": "ओपन सोर्स और वाणिज्यिक मॉड्यूल और थीम आपके व्यावसायिक अनुप्रयोग में उपयोग करने के लिए तैयार हैं।", + "NuGetNPMPackages": "NuGet और NPM पैकेज", + "NuGetNPMPackagesExplanation": "NuGet और NPM पैकेज के रूप में वितरित। स्थापित करने और अपग्रेड करने में आसान।", + "ExtensibleReplaceable": "एक्स्टेंसिबल / बदली", + "ExtensibleReplaceableExplanation": "सभी सेवाओं और मॉड्यूल को ध्यान में रखते हुए डिजाइन किया गया है। आप सेवाओं, पृष्ठों, शैलियों और घटकों को बदल सकते हैं।", + "CrossCuttingConcernsExplanation2": "अपना कोडबेस छोटा रखें ताकि आप उस कोड पर ध्यान केंद्रित कर सकें जो आपके व्यवसाय के लिए विशिष्ट है।", + "CrossCuttingConcernsExplanation3": "कई परियोजनाओं पर सामान्य आवेदन आवश्यकताओं को लागू करने का समय न भेजें।", + "AuthenticationAuthorization": "प्रमाणीकरण प्राधिकरण", + "ExceptionHandling": "संचालन अपवाद", + "Validation": "मान्यकरण", + "DatabaseConnection": "डेटाबेस कनेक्शन", + "TransactionManagement": "आदान - प्रदान प्रबंधन", + "AuditLogging": "ऑडिट लॉगिंग", + "Caching": "कैशिंग", + "Multitenancy": "बहु किरायेदारी", + "DataFiltering": "डेटा फ़िल्टरिंग", + "ConventionOverConfiguration": "कॉन्फिगरेशन पर सम्मलेन", + "ConventionOverConfigurationExplanation": "ABP न्यूनतम या शून्य कॉन्फ़िगरेशन के साथ डिफ़ॉल्ट रूप से सामान्य अनुप्रयोग सम्मेलनों को लागू करता है।", + "ConventionOverConfigurationExplanationList1": "ऑटो निर्भरता इंजेक्शन के लिए सेवाओं को पंजीकृत करता है।", + "ConventionOverConfigurationExplanationList2": "नामकरण सम्मेलनों द्वारा HTTP APIs के रूप में अनुप्रयोग सेवाओं का प्रस्ताव है।", + "ConventionOverConfigurationExplanationList3": "C # और JavaScript के लिए गतिशील HTTP क्लाइंट प्रॉक्सी बनाता है।", + "ConventionOverConfigurationExplanationList4": "आपकी संस्थाओं के लिए डिफ़ॉल्ट रिपॉजिटरी प्रदान करता है।", + "ConventionOverConfigurationExplanationList5": "वेब अनुरोध या एप्लिकेशन सेवा पद्धति के अनुसार कार्य की इकाई का प्रबंधन।", + "ConventionOverConfigurationExplanationList6": "आपकी संस्थाओं के लिए ईवेंट बनाएं, अपडेट करें और हटाएं।", + "BaseClasses": "आधार वर्ग", + "BaseClassesExplanation": "सामान्य अनुप्रयोग पैटर्न के लिए पूर्व-निर्मित आधार कक्षाएं।", + "DeveloperFocusedExplanation": "एबीपी डेवलपर्स के लिए है।", + "DeveloperFocusedExplanationCont": "यह आपके दैनिक सॉफ्टवेयर विकास को सरल बनाने का लक्ष्य रखता है जबकि आपको निम्न स्तर के कोड लिखने से प्रतिबंधित नहीं करता है।", + "SeeAllFeatures": "सभी सुविधाएँ देखें", + "CLI_CommandLineInterface": "सीएलआई (कमांड लाइन इंटरफ़ेस)", + "CLI_CommandLineInterfaceExplanation": "नई परियोजनाओं के निर्माण और नए मॉड्यूल को जोड़ने में मदद करने के लिए एक CLI शामिल है।", + "StartupTemplates": "स्टार्टअप टेम्पलेट", + "StartupTemplatesExplanation": "विभिन्न स्टार्टअप टेम्प्लेट आपके विकास को शुरू करने के लिए पूरी तरह से कॉन्फ़िगर समाधान प्रदान करते हैं।", + "BasedOnFamiliarTools": "परिचित उपकरणों के आधार पर", + "BasedOnFamiliarToolsExplanation": "आप पहले से ही जानते हैं कि लोकप्रिय उपकरणों के साथ निर्मित और एकीकृत। कम सीखने की अवस्था, आसान अनुकूलन, आरामदायक विकास।", + "ORMIndependent": "ORM स्वतंत्र", + "ORMIndependentExplanation": "कोर फ्रेमवर्क ORM / डेटाबेस स्वतंत्र है और किसी भी डेटा स्रोत के साथ काम कर सकता है। इकाई फ्रेमवर्क कोर और MongoDB प्रदाता पहले से ही उपलब्ध हैं।", + "Features": "ABP फ्रेमवर्क सुविधाओं का अन्वेषण करें", + "ABPCLI": "एबीपी सीएलआई", + "Modularity": "प्रतिरूपकता", + "BootstrapTagHelpers": "बूटस्ट्रैप टैग हेल्पर्स", + "DynamicForms": "गतिशील रूप", + "BundlingMinification": "बंडलिंग और न्यूनतमकरण", + "BackgroundJobs": "बैकग्राउंड जॉब्स", + "BackgroundJobsExplanation": "सरल कक्षाओं को परिभाषित करें ताकि पृष्ठभूमि में नौकरियों को निष्पादित किया जा सके। अंतर्निहित नौकरी प्रबंधक का उपयोग करें या अपने स्वयं के एकीकृत करें। Hangfire और RabbitMQ एकीकरण पहले से ही उपलब्ध हैं।", + "DDDInfrastructure": "डीडीडी इन्फ्रास्ट्रक्चर", + "DomainDrivenDesignInfrastructure": "डोमेन संचालित डिज़ाइन इन्फ्रास्ट्रक्चर", + "AutoRESTAPIs": "ऑटो रीस्ट एपीआई", + "DynamicClientProxies": "गतिशील ग्राहक प्रॉक्सी", + "DistributedEventBus": "वितरित इवेंट बस", + "DistributedEventBusWithRabbitMQIntegration": "रैबिटएमक्यू इंटीग्रेशन वाली इवेंट बस वितरित की", + "TestInfrastructure": "टेस्ट इन्फ्रास्ट्रक्चर", + "AuditLoggingEntityHistories": "ऑडिट लॉगिंग और इकाई इतिहास", + "ObjectToObjectMapping": "ऑब्जेक्ट टू ऑब्जेक्ट मैपिंग", + "ObjectToObjectMappingExplanation": "AutoMapper एकीकरण के साथ अमूर्तता के लिए ऑब्जेक्ट मैपिंग पर ऑब्जेक्ट ।", + "EmailSMSAbstractions": "ईमेल और एसएमएस अंश", + "EmailSMSAbstractionsWithTemplatingSupport": "ईमेल और एसएमएस अंशांकन समर्थन के साथ", + "Localization": "स्थानीयकरण", + "SettingManagement": "प्रबंधन की स्थापना", + "ExtensionMethods": "एक्सटेंशन के तरीके", + "ExtensionMethodsHelpers": "एक्सटेंशन के तरीके और मददगार", + "AspectOrientedProgramming": "पहलू आधारित प्रोग्रामिंग", + "DependencyInjection": "निर्भरता अन्तःक्षेपण", + "DependencyInjectionByConventions": "सम्मेलनों द्वारा निर्भरता इंजेक्शन", + "ABPCLIExplanation": "ABP CLI (कमांड लाइन इंटरफेस) ABP आधारित समाधानों के लिए कुछ सामान्य ऑपरेशन करने के लिए एक कमांड लाइन टूल है।", + "ModularityExplanation": "ABP अपने स्वयं के एप्लिकेशन मॉड्यूल बनाने के लिए एक पूर्ण बुनियादी ढांचा प्रदान करता है जिनके पास इकाइयाँ, सेवाएँ, डेटाबेस एकीकरण, API, UI घटक और इतने पर हो सकता है।", + "MultiTenancyExplanation": "एबीपी फ्रेमवर्क न केवल बहु-किरायेदार अनुप्रयोगों को विकसित करने का समर्थन करता है, बल्कि आपके कोड को बहु-किरायेदारी से अनजान बनाता है।", + "MultiTenancyExplanation2": "वर्तमान किरायेदार को स्वचालित रूप से निर्धारित कर सकते हैं, एक दूसरे से अलग किरायेदारों के डेटा को अलग कर सकते हैं।", + "MultiTenancyExplanation3": "एकल डेटाबेस, डेटाबेस प्रति किरायेदार और हाइब्रिड दृष्टिकोण का समर्थन करता है।", + "MultiTenancyExplanation4": "आप अपने व्यवसाय कोड पर ध्यान केंद्रित करते हैं और आपकी ओर से मल्टी-टेनेंसी को संभालने की रूपरेखा तैयार करते हैं।", + "BootstrapTagHelpersExplanation": "बूटस्ट्रैप घटकों के दोहराए गए विवरणों को मैन्युअल रूप से लिखने के बजाय, इसे सरल बनाने और अंतरंगता का लाभ उठाने के लिए एबीपी के टैग सहायकों का उपयोग करें। जब भी आपको जरूरत हो आप बूटस्ट्रैप का इस्तेमाल जरूर कर सकते हैं।", + "DynamicFormsExplanation": "डायनामिक फॉर्म और इनपुट टैग हेल्पर्स मॉडल के रूप में C # क्लास से पूरा फॉर्म बना सकते हैं।", + "AuthenticationAuthorizationExplanation": "रिच प्रमाणीकरण और प्राधिकरण विकल्प ASP.NET कोर आइडेंटिटी और आइडेंटिटी सेवर 4 को एकीकृत करता है। एक एक्स्टेंसिबल और विस्तृत अनुमति प्रणाली प्रदान करता है।", + "CrossCuttingConcernsExplanation": "इन सभी सामान्य चीज़ों को बार-बार लागू करने के लिए अपने आप को दोहराएं नहीं। अपने व्यवसाय कोड पर ध्यान दें और एबीपी को उन्हें सम्मेलनों द्वारा स्वचालित करें।", + "DatabaseConnectionTransactionManagement": "डेटाबेस कनेक्शन और लेनदेन प्रबंधन", + "CorrelationIdTracking": "सहसंबंध-आईडी ट्रैकिंग", + "BundlingMinificationExplanation": "ABP एक सरल, गतिशील, शक्तिशाली, मॉड्यूलर और बिल्ट-इन बंडलिंग और मिनिफिकेशन सिस्टम प्रदान करता है।", + "VirtualFileSystemnExplanation": "वर्चुअल फ़ाइल सिस्टम उन फ़ाइलों को प्रबंधित करना संभव बनाता है जो फ़ाइल सिस्टम (डिस्क) पर भौतिक रूप से मौजूद नहीं हैं। यह मुख्य रूप से विधानसभाओं में (js, css, image, cshtml ...) फ़ाइलों को एम्बेड करने और रनटाइम के दौरान भौतिक फ़ाइलों की तरह उपयोग करने के लिए उपयोग किया जाता है।", + "ThemingExplanation": "थिमिंग सिस्टम नवीनतम बूटस्ट्रैप ढांचे के आधार पर, सामान्य आधार पुस्तकालयों और लेआउट के एक सेट को परिभाषित करके आपके एप्लिकेशन और मॉड्यूल विषय को विकसित करने की अनुमति देता है।", + "DomainDrivenDesignInfrastructureExplanation": "डोमेन संचालित डिज़ाइन पैटर्न और सिद्धांतों के आधार पर स्तरित अनुप्रयोगों के निर्माण के लिए एक पूर्ण बुनियादी ढांचा;", + "Specification": "विनिर्देश", + "Repository": "कोष", + "DomainService": "डोमेन सेवा", + "ValueObject": "मान वस्तु", + "ApplicationService": "आवेदन सेवा", + "DataTransferObject": "डेटा ट्रांसफर ऑब्जेक्ट", + "AggregateRootEntity": "एग्रिगेट रूट, एंटिटी", + "AutoRESTAPIsExplanation": "एबीपी कन्वेंशन द्वारा एपीआई कंट्रोलर के रूप में आपकी एप्लिकेशन सेवाओं को स्वचालित रूप से कॉन्फ़िगर कर सकता है।", + "DynamicClientProxiesExplanation": "आसानी से जावास्क्रिप्ट और सी # क्लाइंट से अपने एपीआई का उपभोग करें।", + "DistributedEventBusWithRabbitMQIntegrationExplanation": "बिल्ट-इन डिस्ट्रीब्यूटेड इवेंट बस का उपयोग करके आसानी से प्रकाशित और उपभोग की गई घटनाओं को उपलब्ध करें।", + "TestInfrastructureExplanation": "फ्रेमवर्क को यूनिट और एकीकरण परीक्षण को ध्यान में रखते हुए विकसित किया गया है। यह आसान बनाने के लिए आपको आधार कक्षाएं प्रदान करता है। स्टार्टअप टेम्प्लेट परीक्षण के लिए पूर्व-कॉन्फ़िगर के साथ आते हैं।", + "AuditLoggingEntityHistoriesExplanation": "व्यावसायिक महत्वपूर्ण अनुप्रयोगों के लिए अंतर्निहित ऑडिट लॉगिंग। संपत्ति स्तर के विवरण के साथ अनुरोध, सेवा, विधि स्तर ऑडिट लॉगिंग और इकाई इतिहास।", + "EmailSMSAbstractionsWithTemplatingSupportExplanation": "IEmailSender और ISmsSender अमूर्त बुनियादी ढांचे से आपके आवेदन के तर्क को विघटित करते हैं। उन्नत ईमेल टेम्प्लेट सिस्टम ईमेल टेम्प्लेट बनाने और स्थानीय बनाने और जब भी आवश्यकता हो आसानी से उपयोग करने की अनुमति देता है।", + "LocalizationExplanation": "स्थानीयकरण प्रणाली सादे JSON फ़ाइलों में संसाधन बनाने और उन्हें आपके UI को स्थानीय बनाने के लिए उपयोग करने की अनुमति देती है। यह वंशानुक्रम, एक्सटेंशन और जावास्क्रिप्ट एकीकरण जैसे उन्नत परिदृश्यों का समर्थन करता है, जबकि यह AspNet Core के स्थानीयकरण प्रणाली के साथ पूरी तरह से संगत है।", + "SettingManagementExplanation": "अपने आवेदन के लिए सेटिंग्स को परिभाषित करें और वर्तमान कॉन्फ़िगरेशन, किरायेदार और उपयोगकर्ता के आधार पर रनटाइम पर मान प्राप्त करें।", + "ExtensionMethodsHelpersExplanation": "तुच्छ कोड भागों के लिए भी अपने आप को दोहराएं नहीं। मानक प्रकारों के लिए एक्सटेंशन और हेल्पर्स आपके कोड को बहुत क्लीनर और लिखने में आसान बनाते हैं।", + "AspectOrientedProgrammingExplanation": "गतिशील परदे के पीछे बनाने और पहलू ओरिएंटेड प्रोग्रामिंग को लागू करने के लिए एक आरामदायक बुनियादी ढांचा प्रदान करता है। किसी भी वर्ग को इंटरसेप्ट करें और हर विधि के निष्पादन से पहले और बाद में अपने कोड को निष्पादित करें।", + "DependencyInjectionByConventionsExplanation": "मैन्युअल रूप से निर्भरता इंजेक्शन के लिए अपनी कक्षाओं को पंजीकृत करने की आवश्यकता नहीं है। कन्वेंशन द्वारा स्वचालित रूप से आम सेवा प्रकारों को पंजीकृत करता है। अन्य प्रकार की सेवाओं के लिए, आप इसे आसान और सरल बनाने के लिए इंटरफेस और विशेषताओं का उपयोग कर सकते हैं।", + "DataFilteringExplanation": "उन डेटा फ़िल्टर को परिभाषित और उपयोग करें जो डेटाबेस से क्वेरी करने पर स्वचालित रूप से लागू होते हैं। जब आप साधारण इंटरफ़ेस लागू करते हैं, तो सॉफ्ट डिलीट और मल्टीटेन्नेर फिल्टर बॉक्स से बाहर दिए जाते हैं।", + "PublishEvents": "घटनाक्रम प्रकाशित करें", + "HandleEvents": "घटनाएँ संभालें", + "AndMore": "और अधिक...", + "Code": "कोड", + "Result": "परिणाम", + "SeeTheDocumentForMoreInformation": "अधिक जानकारी के लिए {0} दस्तावेज़ देखें", + "IndexPageHeroSection": "<स्पैन क्लास = \"फर्स्ट-लाइन शाइन\"> ओपन सोर्स <स्पैन क्लास = \"सेकंड-लाइन टेक्स्ट-अपरकेस\"> वेब एप्लिकेशन
फ्रेमवर्क asp.net core के लिए ", + "UiFramework": "यूआई फ्रेमवर्क", + "EmailAddress": "ईमेल पता", + "Mobile": "मोबाइल", + "ReactNative": "प्रतिक्रियाशील मूलनिवासी", + "Strong": "मजबूत", + "Complete": "पूर्ण", + "BasedLayeringModel": "आधारित लेयरिंग मॉडल", + "Microservice": "माइक्रो सर्विस", + "Compatible": "संगत", + "MeeTTheABPCommunityInfo": "हमारा मिशन एक ऐसा वातावरण बनाना है जहां डेवलपर्स लेख, ट्यूटोरियल, केस स्टडी आदि के साथ एक-दूसरे की मदद कर सकें और समान विचारधारा वाले लोगों से मिल सकें।", + "JoinTheABPCommunityInfo": "एक जीवंत समुदाय के साथ शामिल हों और ABP फ्रेमवर्क में योगदानकर्ता बनें!", + "AllArticles": "सभी चीज़ें", + "SubmitYourArticle": "अपना लेख प्रस्तुत करें", + "DynamicClientProxyDocument": " JavaScript और C # के लिए डायनेमिक क्लाइंट प्रॉक्सी दस्तावेज़ देखें।", + "EmailSMSAbstractionsDocument": "अधिक जानकारी के लिए ईमेल करना और एसएमएस भेजने के दस्तावेज़ देखें।", + "CreateProjectWizard": "यह विज़ार्ड स्टार्टअप टेम्प्लेट से एक नई परियोजना बनाता है जो आपकी परियोजना को शुरू करने के लिए ठीक से कॉन्फ़िगर किया गया है।", + "TieredOption": "एक ऐसा समाधान तैयार करता है जहाँ वेब और Http API परतें शारीरिक रूप से अलग हो जाती हैं। यदि जांच नहीं की जाती है, तो एक स्तरित समाधान बनाता है जो कम जटिल है और अधिकांश परिदृश्यों के लिए उपयुक्त है।", + "SeparateIdentityServerOption": "सर्वर एप्लिकेशन को दो अनुप्रयोगों में अलग करता है: पहला पहचान सर्वर के लिए है और दूसरा आपके सर्वर साइड HTTP एपीआई के लिए है।", + "UseslatestPreVersion": "नवीनतम पूर्व-रिलीज़ संस्करण का उपयोग करता है", + "ReadTheDocumentation": "<स्पैन क्लास = \"टेक्स्ट-प्राइमरी\"> पढ़ें <स्पैन क्लास = \"टेक्स्ट-सक्सेस\"> डॉक्यूमेंटेशन ", + "Documentation": "प्रलेखन", + "GettingStartedTutorial": "स्टार्टिंग ट्यूटोरियल", + "ApplicationDevelopmentTutorial": "अनुप्रयोग विकास ट्यूटोरियल", + "TheStartupTemplate": "स्टार्टअप टेम्पलेट", + "InstallABPCLIInfo": "एबीपी सीएलआई एबीपी ढांचे के साथ एक नया समाधान शुरू करने का सबसे तेज़ तरीका है। कमांड लाइन विंडो का उपयोग करके ABP CLI स्थापित करें:", + "DifferentLevelOfNamespaces": "आप विभिन्न स्तरों के नामस्थानों का उपयोग कर सकते हैं; जैसे BookStore, Acme.BookStore या Acme.Retail.BookStore।", + "ABPCLIExamplesInfo": " नया कमांड डेटाबेस प्रदाता के रूप में एंटिटी फ्रेमवर्क कोर के साथ स्तरित MVC एप्लिकेशन बनाता है। हालांकि, इसके पास अतिरिक्त विकल्प हैं। उदाहरण:", + "SeeCliDocumentForMoreInformation": "अधिक विकल्पों के लिए ABP CLI दस्तावेज़ देखें या ऊपर \"डायरेक्ट डाउनलोड\" टैब चुनें।", + "Optional": "ऐच्छिक", + "LocalFrameworkRef": "फ्रेमवर्क पैकेज के लिए स्थानीय प्रोजेक्ट संदर्भ रखें।", + "BlobStoring": "ब्लॉब भंडारण", + "BlobStoringExplanation": "BLOB भंडारण प्रणाली BLOBs के साथ काम करने के लिए एक अमूर्तता प्रदान करती है। एबीपी कुछ प्री-बिल्ट स्टोरेज प्रोवाइडर इंटीग्रेशन (एज़्योर, एडब्ल्यूएस, फाइल सिस्टम, डेटाबेस इत्यादि) प्रदान करता है जिन्हें आप आसानी से अपने अनुप्रयोगों में उपयोग कर सकते हैं।", + "TextTemplating": "पाठ अस्थायी", + "TextTemplatingExplanation": "टेम्प्लेट टेम्प्लेटिंग का उपयोग टेम्प्लेट और मॉडल (डेटा ऑब्जेक्ट) के आधार पर सामग्री को गतिशील रूप से प्रस्तुत करने के लिए किया जाता है। उदाहरण के लिए, आप पूर्व-निर्मित टेम्पलेट के साथ गतिशील ईमेल सामग्री बनाने के लिए इसका उपयोग कर सकते हैं।", + "MultipleUIOptions": "एकाधिक यूआई विकल्प", + "MultipleDBOptions": "एकाधिक डेटाबेस प्रदाता", + "MultipleUIOptionsExplanation": "कोर फ्रेमवर्क को यूआई स्वतंत्र के रूप में डिज़ाइन किया गया है और यह किसी भी प्रकार के यूआई सिस्टम के साथ काम कर सकता है, जबकि कई पूर्व-निर्मित और एकीकृत विकल्प बॉक्स से बाहर प्रदान किए गए हैं।", + "MultipleDBOptionsExplanation": "रूपरेखा किसी भी डेटा स्रोत के साथ काम कर सकती है, जबकि निम्नलिखित प्रदाता आधिकारिक रूप से विकसित और समर्थित हैं;", + "SelectLanguage": "भाषा का चयन करें", + "LatestArticleOnCommunity": "एबीपी समुदाय पर नवीनतम लेख", + "Register": "रजिस्टर करें", + "IsDownloadable": "डाउनलोड करने योग्य है" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json new file mode 100644 index 0000000000..e4cdc73bf2 --- /dev/null +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json @@ -0,0 +1,202 @@ +{ + "culture": "it", + "texts": { + "GetStarted": "Inizia - Modelli di avvio", + "Create": "Creare", + "NewProject": "Nuovo progetto", + "DirectDownload": "Download diretto", + "ProjectName": "Nome del progetto", + "ProjectType": "Tipo di progetto", + "DatabaseProvider": "Provider di database", + "DatabaseManagementSystem": "Sistema di gestione del database", + "NTier": "N-Tier", + "IncludeUserInterface": "Includi l'interfaccia utente", + "CreateNow": "Crea adesso", + "TheStartupProject": "Il progetto di avvio", + "Tutorial": "Tutorial", + "UsingCLI": "Utilizzo della CLI", + "SeeDetails": "Vedi i dettagli", + "AbpShortDescription": "ABP Framework è un'infrastruttura completa per creare applicazioni Web moderne seguendo le migliori pratiche e convenzioni di sviluppo software.", + "SourceCodeUpper": "CODICE SORGENTE", + "LatestReleaseLogs": "Ultimi registri di rilascio", + "Infrastructure": "Infrastruttura", + "Architecture": "Architettura", + "Modular": "Modulare", + "DontRepeatYourself": "Non ripetere te stesso", + "DeveloperFocused": "Concentrato sullo sviluppatore", + "FullStackApplicationInfrastructure": "Infrastruttura applicativa full stack.", + "DomainDrivenDesign": "Progettazione basata sul dominio", + "DomainDrivenDesignExplanation": "Progettato e sviluppato sulla base di modelli e principi DDD. Fornisce un modello a più livelli per la tua applicazione.", + "Authorization": "Autorizzazione", + "AuthorizationExplanation": "Autorizzazione avanzata con utente, ruolo e sistema di autorizzazioni granulare. Basato sulla libreria Microsoft Identity.", + "MultiTenancy": "Multi-Tenancy", + "MultiTenancyExplanationShort": "Applicazioni SaaS rese facili! Multi-tenancy integrato dal database all'interfaccia utente.", + "CrossCuttingConcerns": "Preoccupazioni trasversali", + "CrossCuttingConcernsExplanationShort": "Infrastruttura completa per autorizzazione, convalida, gestione delle eccezioni, memorizzazione nella cache, registrazione di audit, gestione delle transazioni e altro ancora.", + "BuiltInBundlingMinification": "Raggruppamento e minimizzazione incorporati", + "BuiltInBundlingMinificationExplanation": "Non è necessario utilizzare strumenti esterni per raggruppare e minimizzare. ABP offre un modo più semplice, dinamico, potente, modulare e integrato!", + "VirtualFileSystem": "File system virtuale", + "VirtualFileSystemExplanation": "Incorpora viste, script, stili, immagini ... in pacchetti / librerie e riutilizzali in diverse applicazioni.", + "Theming": "Theming", + "ThemingExplanationShort": "Usa e personalizza il tema dell'interfaccia utente standard basato su bootstrap o creane uno tuo.", + "BootstrapTagHelpersDynamicForms": "Bootstrap Tag Helpers e moduli dinamici", + "BootstrapTagHelpersDynamicFormsExplanation": "Invece di scrivere manualmente i dettagli ripetuti dei componenti bootstrap, usa gli helper tag di ABP per semplificarlo e sfruttare intellisense. Crea rapidamente moduli dell'interfaccia utente basati su un modello C # utilizzando l'helper tag del modulo dinamico.", + "HTTPAPIsDynamicProxies": "API HTTP e proxy dinamici", + "HTTPAPIsDynamicProxiesExplanation": "Esponi automaticamente i servizi dell'applicazione come API HTTP in stile REST e utilizzali con JavaScript dinamici e proxy C #.", + "CompleteArchitectureInfo": "Architettura moderna per creare soluzioni software manutenibili.", + "DomainDrivenDesignBasedLayeringModelExplanation": "Aiuta a implementare un'architettura a strati basata su DDD e a costruire una base di codice gestibile.", + "DomainDrivenDesignBasedLayeringModelExplanationCont": "Fornisce modelli di avvio, astrazioni, classi di base, servizi, documentazione e guide per aiutarti a sviluppare la tua applicazione in base a modelli e principi DDD.", + "MicroserviceCompatibleModelExplanation": "Il framework principale ei moduli di pre-compilazione sono progettati pensando all'architettura dei microservizi.", + "MicroserviceCompatibleModelExplanationCont": "Fornisce infrastruttura, integrazioni, campioni e documentazione per implementare più facilmente soluzioni di microservizi, mentre non apporta ulteriore complessità se si desidera un'applicazione monolitica.", + "ModularInfo": "ABP fornisce un sistema di moduli che consente di sviluppare moduli applicativi riutilizzabili, collegarsi agli eventi del ciclo di vita dell'applicazione ed esprimere le dipendenze tra le parti principali del sistema.", + "PreBuiltModulesThemes": "Moduli e temi predefiniti", + "PreBuiltModulesThemesExplanation": "Moduli e temi open source e commerciali sono pronti per l'uso nella tua applicazione aziendale.", + "NuGetNPMPackages": "Pacchetti NuGet e NPM", + "NuGetNPMPackagesExplanation": "Distribuito come pacchetti NuGet e NPM. Facile da installare e aggiornare.", + "ExtensibleReplaceable": "Estensibile / sostituibile", + "ExtensibleReplaceableExplanation": "Tutti i servizi e i moduli sono progettati tenendo conto dell'estensibilità. Puoi sostituire servizi, pagine, stili e componenti.", + "CrossCuttingConcernsExplanation2": "Mantieni la tua base di codice più piccola in modo da poter concentrarti sul codice specifico per la tua attività.", + "CrossCuttingConcernsExplanation3": "Non dedicare tempo all'implementazione dei requisiti delle applicazioni comuni su più progetti.", + "AuthenticationAuthorization": "Autenticazione e autorizzazione", + "ExceptionHandling": "La gestione delle eccezioni", + "Validation": "Validazione", + "DatabaseConnection": "Connessione al database", + "TransactionManagement": "Gestione delle transazioni", + "AuditLogging": "Registrazione di audit", + "Caching": "Caching", + "Multitenancy": "Multitenancy", + "DataFiltering": "Filtraggio dei dati", + "ConventionOverConfiguration": "Convenzione sulla configurazione", + "ConventionOverConfigurationExplanation": "ABP implementa convenzioni di applicazioni comuni per impostazione predefinita con una configurazione minima o zero.", + "ConventionOverConfigurationExplanationList1": "Registra automaticamente i servizi noti per l'inserimento delle dipendenze.", + "ConventionOverConfigurationExplanationList2": "Espone i servizi dell'applicazione come API HTTP mediante convenzioni di denominazione.", + "ConventionOverConfigurationExplanationList3": "Crea proxy client HTTP dinamici per C # e JavaScript.", + "ConventionOverConfigurationExplanationList4": "Fornisce archivi predefiniti per le tue entità.", + "ConventionOverConfigurationExplanationList5": "Gestisce l'unità di lavoro per richiesta Web o metodo di servizio dell'applicazione.", + "ConventionOverConfigurationExplanationList6": "Pubblica creare, aggiornare ed eliminare eventi per le tue entità.", + "BaseClasses": "Classi di base", + "BaseClassesExplanation": "Classi di base predefinite per modelli di applicazioni comuni.", + "DeveloperFocusedExplanation": "ABP è per gli sviluppatori.", + "DeveloperFocusedExplanationCont": "Ha lo scopo di semplificare lo sviluppo quotidiano del software senza impedirti di scrivere codice di basso livello.", + "SeeAllFeatures": "Visualizza tutte le funzionalità", + "CLI_CommandLineInterface": "CLI (Command Line Interface)", + "CLI_CommandLineInterfaceExplanation": "Include una CLI per aiutarti ad automatizzare la creazione di nuovi progetti e l'aggiunta di nuovi moduli.", + "StartupTemplates": "Modelli di avvio", + "StartupTemplatesExplanation": "Vari modelli di avvio forniscono una soluzione completamente configurata per avviare rapidamente lo sviluppo.", + "BasedOnFamiliarTools": "Basato su strumenti familiari", + "BasedOnFamiliarToolsExplanation": "Costruito e integrato con strumenti popolari che già conosci. Bassa curva di apprendimento, facile adattamento, sviluppo confortevole.", + "ORMIndependent": "ORM indipendente", + "ORMIndependentExplanation": "Il framework principale è indipendente da ORM / database e può funzionare con qualsiasi origine dati. I provider di Entity Framework Core e MongoDB sono già disponibili.", + "Features": "Esplora le funzionalità di ABP Framework", + "ABPCLI": "ABP CLI", + "Modularity": "Modularità", + "BootstrapTagHelpers": "Bootstrap Tag Helpers", + "DynamicForms": "Forme dinamiche", + "BundlingMinification": "Raggruppamento e minimizzazione", + "BackgroundJobs": "Lavori in background", + "BackgroundJobsExplanation": "Definire classi semplici per eseguire lavori in background come in coda. Usa il gestore dei lavori integrato o integra il tuo. Le integrazioni Hangfire e RabbitMQ sono già disponibili.", + "DDDInfrastructure": "Infrastruttura DDD", + "DomainDrivenDesignInfrastructure": "Infrastruttura di progettazione basata sul dominio", + "AutoRESTAPIs": "API REST automatiche", + "DynamicClientProxies": "Proxy client dinamici", + "DistributedEventBus": "Bus di eventi distribuito", + "DistributedEventBusWithRabbitMQIntegration": "Bus di eventi distribuito con integrazione RabbitMQ", + "TestInfrastructure": "Infrastruttura di test", + "AuditLoggingEntityHistories": "Registrazione di audit e cronologie delle entità", + "ObjectToObjectMapping": "Mappatura da oggetto a oggetto", + "ObjectToObjectMappingExplanation": "Astrazione della mappatura da oggetto a oggetto con integrazione AutoMapper.", + "EmailSMSAbstractions": "Astrazioni tramite e-mail e SMS", + "EmailSMSAbstractionsWithTemplatingSupport": "Astrazioni tramite posta elettronica e SMS con supporto per i modelli", + "Localization": "Localizzazione", + "SettingManagement": "Gestione delle impostazioni", + "ExtensionMethods": "Metodi di estensione", + "ExtensionMethodsHelpers": "Metodi di estensione e aiutanti", + "AspectOrientedProgramming": "Programmazione orientata agli aspetti", + "DependencyInjection": "Iniezione di dipendenza", + "DependencyInjectionByConventions": "Inserimento delle dipendenze mediante convenzioni", + "ABPCLIExplanation": "ABP CLI (Command Line Interface) è uno strumento a riga di comando per eseguire alcune operazioni comuni per soluzioni basate su ABP.", + "ModularityExplanation": "ABP fornisce un'infrastruttura completa per creare i propri moduli applicativi che possono avere entità, servizi, integrazione di database, API, componenti dell'interfaccia utente e così via.", + "MultiTenancyExplanation": "Il framework ABP non solo supporta lo sviluppo di applicazioni multi-tenant, ma rende anche il tuo codice per lo più inconsapevole del multi-tenancy.", + "MultiTenancyExplanation2": "Può determinare automaticamente l'inquilino corrente, isolare i dati di diversi inquilini l'uno dall'altro.", + "MultiTenancyExplanation3": "Supporta database singolo, database per tenant e approcci ibridi.", + "MultiTenancyExplanation4": "Ti concentri sul tuo codice aziendale e lasci che il framework gestisca il multi-tenancy per tuo conto.", + "BootstrapTagHelpersExplanation": "Invece di scrivere manualmente i dettagli ripetuti dei componenti bootstrap, usa gli helper tag di ABP per semplificarlo e sfruttare intellisense. Puoi sicuramente usare Bootstrap ogni volta che ne hai bisogno.", + "DynamicFormsExplanation": "Gli helper dei moduli dinamici e dei tag di input possono creare il modulo completo da una classe C # come modello.", + "AuthenticationAuthorizationExplanation": "Ricche opzioni di autenticazione e autorizzazione integrate in ASP.NET Core Identity & IdentityServer4. Fornisce un sistema di autorizzazione estensibile e dettagliato.", + "CrossCuttingConcernsExplanation": "Non ripetere te stesso per implementare tutte queste cose comuni ancora e ancora. Concentrati sul tuo codice aziendale e lascia che ABP li automatizzi secondo le convenzioni.", + "DatabaseConnectionTransactionManagement": "Connessione al database e gestione delle transazioni", + "CorrelationIdTracking": "Monitoraggio dell'ID di correlazione", + "BundlingMinificationExplanation": "ABP offre un sistema di raggruppamento e minimizzazione semplice, dinamico, potente, modulare e integrato.", + "VirtualFileSystemnExplanation": "Il Virtual File System consente di gestire file che non esistono fisicamente nel file system (disco). Viene utilizzato principalmente per incorporare file (js, css, immagine, cshtml ...) negli assembly e utilizzarli come file fisici in runtime.", + "ThemingExplanation": "Il sistema di temi consente di sviluppare applicazioni e moduli indipendentemente dal tema definendo un set di librerie e layout di base comuni, basati sul più recente framework Bootstrap.", + "DomainDrivenDesignInfrastructureExplanation": "Un'infrastruttura completa per creare applicazioni a più livelli basate sui modelli e sui principi di Domain Driven Design;", + "Specification": "Specifica", + "Repository": "Repository", + "DomainService": "Servizio di dominio", + "ValueObject": "Oggetto valore", + "ApplicationService": "Servizio applicazioni", + "DataTransferObject": "Oggetto trasferimento dati", + "AggregateRootEntity": "Radice aggregata, entità", + "AutoRESTAPIsExplanation": "ABP può configurare automaticamente i servizi dell'applicazione come controller API per convenzione.", + "DynamicClientProxiesExplanation": "Utilizza facilmente le tue API da client JavaScript e C #.", + "DistributedEventBusWithRabbitMQIntegrationExplanation": "Pubblica e utilizza facilmente eventi distribuiti utilizzando Distributed Event Bus integrato con integrazione RabbitMQ disponibile.", + "TestInfrastructureExplanation": "Il framework è stato sviluppato in mente per test di unità e integrazione. Fornisce classi di base per renderlo più facile. I modelli di avvio vengono forniti preconfigurati per i test.", + "AuditLoggingEntityHistoriesExplanation": "Registrazione di audit integrata per applicazioni business-critical. Richiesta, servizio, registrazione di controllo a livello di metodo e cronologie di entità con dettagli a livello di proprietà.", + "EmailSMSAbstractionsWithTemplatingSupportExplanation": "Le astrazioni di IEmailSender e ISmsSender separano la logica dell'applicazione dall'infrastruttura. Il sistema avanzato di modelli di posta elettronica consente di creare e localizzare modelli di posta elettronica e di utilizzarli facilmente quando necessario.", + "LocalizationExplanation": "Il sistema di localizzazione consente di creare risorse in semplici file JSON e utilizzarli per localizzare la tua interfaccia utente. Supporta scenari avanzati come ereditarietà, estensioni e integrazione JavaScript mentre è completamente compatibile con il sistema di localizzazione di AspNet Core.", + "SettingManagementExplanation": "Definisci le impostazioni per la tua applicazione e ottieni i valori in fase di esecuzione in base alla configurazione, al tenant e all'utente correnti.", + "ExtensionMethodsHelpersExplanation": "Non ripeterti nemmeno per parti di codice banali. Le estensioni e gli helper per i tipi standard rendono il codice molto più pulito e facile da scrivere.", + "AspectOrientedProgrammingExplanation": "Fornisce una comoda infrastruttura per creare proxy dinamici e implementare la programmazione orientata agli aspetti. Intercetta qualsiasi classe ed esegui il codice prima e dopo l'esecuzione di ogni metodo.", + "DependencyInjectionByConventionsExplanation": "Non è necessario registrare manualmente le classi per l'inserimento delle dipendenze. Registra automaticamente i tipi di servizio comuni per convenzione. Per altri tipi di servizi, puoi utilizzare interfacce e attributi per renderlo più semplice e sul posto.", + "DataFilteringExplanation": "Definisci e utilizza i filtri di dati che vengono applicati automaticamente quando esegui query sulle entità dal database. Quando si implementano interfacce semplici, vengono forniti filtri Soft Delete e MultiTenant.", + "PublishEvents": "Pubblica eventi", + "HandleEvents": "Gestisci eventi", + "AndMore": "e altro ancora ...", + "Code": "Codice", + "Result": "Risultato", + "SeeTheDocumentForMoreInformation": "Consulta il {0} documento per ulteriori informazioni", + "IndexPageHeroSection": " open source Framework
applicazione web
per asp.net core ", + "UiFramework": "Framework dell'interfaccia utente", + "EmailAddress": "Indirizzo e-mail", + "Mobile": "Mobile", + "ReactNative": "React Native", + "Strong": "Forte", + "Complete": "Completare", + "BasedLayeringModel": "Modello di stratificazione basato", + "Microservice": "Microservizio", + "Compatible": "Compatibile", + "MeeTTheABPCommunityInfo": "La nostra missione è creare un ambiente in cui gli sviluppatori possano aiutarsi a vicenda con articoli, tutorial, casi di studio, ecc. E incontrare persone che la pensano allo stesso modo.", + "JoinTheABPCommunityInfo": "Fatti coinvolgere da una vivace comunità e diventa un collaboratore di ABP Framework!", + "AllArticles": "Tutti gli articoli", + "SubmitYourArticle": "Invia il tuo articolo", + "DynamicClientProxyDocument": "Consulta la documentazione relativa al proxy del client dinamico per JavaScript e C # .", + "EmailSMSAbstractionsDocument": "Per ulteriori informazioni, consulta i documenti di invio di email e invio di SMS .", + "CreateProjectWizard": "Questa procedura guidata crea un nuovo progetto dal modello di avvio che è configurato correttamente per avviare rapidamente il progetto.", + "TieredOption": "Crea una soluzione a più livelli in cui i livelli API Web e Http sono fisicamente separati. Se non selezionata, crea una soluzione a più livelli meno complessa e adatta alla maggior parte degli scenari.", + "SeparateIdentityServerOption": "Separa il lato server in due applicazioni: la prima è per il server di identità e la seconda è per l'API HTTP lato server.", + "UseslatestPreVersion": "Utilizza l'ultima versione pre-rilascio", + "ReadTheDocumentation": " Leggi La documentazione ", + "Documentation": "Documentazione", + "GettingStartedTutorial": "Tutorial introduttivo", + "ApplicationDevelopmentTutorial": "Tutorial sullo sviluppo di applicazioni", + "TheStartupTemplate": "Il modello di avvio", + "InstallABPCLIInfo": "ABP CLI è il modo più veloce per avviare una nuova soluzione con il framework ABP. Installa ABP CLI utilizzando una finestra della riga di comando:", + "DifferentLevelOfNamespaces": "È possibile utilizzare diversi livelli di spazi dei nomi; per esempio. BookStore, Acme.BookStore o Acme.Retail.BookStore.", + "ABPCLIExamplesInfo": "Il comando nuovo crea un ' applicazione MVC a più livelli con Entity Framework Core come provider di database. Tuttavia, ha opzioni aggiuntive. Esempi:", + "SeeCliDocumentForMoreInformation": "Consulta il documento ABP CLI per ulteriori opzioni o seleziona la scheda \"Download diretto\" in alto.", + "Optional": "Opzionale", + "LocalFrameworkRef": "Mantieni il riferimento al progetto locale per i pacchetti del framework.", + "BlobStoring": "Archiviazione BLOB", + "BlobStoringExplanation": "Il sistema di archiviazione BLOB fornisce un'astrazione per lavorare con i BLOB. ABP fornisce alcune integrazioni di provider di archiviazione predefinite (Azure, AWS, File System, Database e così via) che puoi facilmente utilizzare nelle tue applicazioni.", + "TextTemplating": "Modelli di testo", + "TextTemplatingExplanation": "La creazione di modelli di testo viene utilizzata per eseguire il rendering dinamico dei contenuti in base a un modello e un modello (un oggetto dati). Ad esempio, puoi utilizzarlo per creare contenuti di posta elettronica dinamici con un modello predefinito.", + "MultipleUIOptions": "Molteplici opzioni di interfaccia utente", + "MultipleDBOptions": "Più fornitori di database", + "MultipleUIOptionsExplanation": "Il framework principale è progettato come indipendente dall'interfaccia utente e può funzionare con qualsiasi tipo di sistema di interfaccia utente, mentre sono disponibili più opzioni predefinite e integrate.", + "MultipleDBOptionsExplanation": "Il framework può funzionare con qualsiasi fonte di dati, mentre i seguenti provider sono ufficialmente sviluppati e supportati;", + "SelectLanguage": "Seleziona la lingua", + "LatestArticleOnCommunity": "Ultimo articolo sulla comunità ABP", + "Register": "Registrati", + "IsDownloadable": "È scaricabile" + } +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json index ef4ecbdcac..0da4a44beb 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json @@ -157,6 +157,41 @@ "EmailAddress": "E-Posta Adresi", "Mobile": "Mobil", "ReactNative": "React Native", - "SelectLanguage": "Dil seçin" + "SelectLanguage": "Dil seçin", + "Register": "Kayıt ol", + "IsDownloadable": "Yüklenebilir mi", + "DatabaseOptions": "Veritabanı Seçenekleri", + "BackToPackagesPage": "Paketler sayfasına geri dön", + "HowToInstall": "Nasıl Indirilir", + "SeeOnNpm": "NPM'de görüntüle", + "SeeOnNuget": "Nuget'de görüntüle", + "MVCGulpCommandExplanation": "Arayüz uygulaması olarak MVC (Razor Page) kullanıyorsanız, paketlerin indirilmesinden sonra \"gulp\" komutunu çalıştırın.", + "UsingABPCLI": "ABP CLI Kullanımı", + "WithoutABPCLI": "ABP CLI kullanmadan", + "ABPCLIModuleDependency": "ABP CLI otomatik olarak modül bağımlılıklarını ekler.", + "AddModuleDependency": "Modül bağımlılıklarını ekleyin", + "Packages": "Paketler", + "NugetPackages": "Nuget Paketleri", + "NPMPackages": "NPM Paketleri", + "SeeDocs": "Dökümanı Görüntüle", + "None": "Hiç", + "Application": "Uygulama", + "Module": "Modül", + "PackageName": "Paket adı", + "LicenseURL": "Lisans Linki", + "License": "Lisans", + "ProjectCreationSuccessMessage": "Projeniz başarıyla oluşturulmuştur", + "HowToRunSolution": "Uygulamayı Nasıl Çalıştırabiliriz?", + "GettingStartedMessage": "Uygulamanızı nasıl yapılandıracağınızı ve çalıştıracağınızı öğrenmek için başlanıç dökümanına bakınız.", + "WebAppDevTutorial": "Web Uygulaması Geliştirme Öğreticisi", + "WebAppDevTutorialMessage": "Adım adım web uygulaması geliştirme örneği için web uygulaması geliştirme öğreticisine bakınız.", + "CommunityArticles": "Topluluk Makaleleri", + "CommunityArticleMessage": "ABP Framework ile ilgili yararlı makaleleri okumak için ABP Topluluk Platformu'na bakın.", + "InvestigateSolutionDetails": "Çözüm detaylarını inceleyin", + "StartupTemplateDocumentationMessage": "Çözümünüzün mimarisini ve yapısını öğrenmek için uygulama başlangıç şablonu belgesine bakın.", + "ClientSideDevelopment": "İstemci Tarafı Geliştirme", + "ClientSideDevelopmentDocumentationMessage": "Kullanıcı arayüzü (istemci tarafı) geliştirmeyle ilgili temel noktaları öğrenmek için {0} belgesine bakın.", + "DatabaseProviderDocumentationMessage": "Veritabanı katmanı geliştirmeyle ilgili temel noktaları öğrenmek için {0} belgesine bakın.", + "ABPCommercialExplanationMessage": "ABP Commercial, ABP Framework için premium modüller, temalar, araçlar ve destek sağlar." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json index 8185ead8cd..27505e138c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json @@ -196,6 +196,39 @@ "MultipleDBOptionsExplanation": "该框架可以使用任何数据源,并且以下提供程序已得到正式开发和支持;", "SelectLanguage": "选择语言", "LatestArticleOnCommunity": "关于ABP社区的最新文章", - "Register": "寄存器" + "Register": "注册", + "DatabaseOptions": "数据库选项", + "BackToPackagesPage": "回到包页面", + "HowToInstall": "如何安装", + "SeeOnNpm": "在NPM查看", + "SeeOnNuget": "在Nuget查看", + "MVCGulpCommandExplanation": "如果你使用MVC (Razor Pages) UI,在包安装完成后运行 \"gulp\" 命令.", + "UsingABPCLI": "使用 Abp CLI", + "WithoutABPCLI": "不使用 ABP CLI", + "ABPCLIModuleDependency": "ABP CLI会自动添加模块依赖.", + "AddModuleDependency": "然后添加模块依赖", + "Packages": "包", + "NugetPackages": "Nuget包", + "NPMPackages": "NPM包", + "SeeDocs": "查看文档", + "None": "空", + "Application": "应用程序", + "Module": "模块", + "PackageName": "包名称", + "LicenseURL": "许可URL", + "License": "许可", + "ProjectCreationSuccessMessage": "你的项目创建成功", + "HowToRunSolution": "如何运行你的解决方案n?", + "GettingStartedMessage": "查看入门文档了解如何配置和运行你的解决方案.", + "WebAppDevTutorial": "Web App 开发教程", + "WebAppDevTutorialMessage": "查看web应用程序开发教程文档,一步一步的开发示例.", + "CommunityArticles": "社区文档", + "CommunityArticleMessage": "查看ABP社区平台来阅读关于ABP框架的文档.", + "InvestigateSolutionDetails": "调查解决方案细节", + "StartupTemplateDocumentationMessage": "查看应用程序启动模板文档来学习你的解决方案架构和结构.", + "ClientSideDevelopment": "客户端部分开发", + "ClientSideDevelopmentDocumentationMessage": "查看{0}文档来学习用户页面(客户端部分)开发.", + "DatabaseProviderDocumentationMessage": "查看{0}文档来学习用数据库层开发.", + "ABPCommercialExplanationMessage": "ABP商业版为ABP框架提供了高级模块,主题,工具和支持." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json index 37f6747ea0..635abfc2fb 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json @@ -155,6 +155,41 @@ "IndexPageHeroSection": "asp.net core的開源Web應用程式
框架
", "UiFramework": "UI框架", "EmailAddress": "電子信箱地址", - "SelectLanguage": "选择语言" + "SelectLanguage": "选择语言", + "LatestArticleOnCommunity": "關於ABP社區的最新文章", + "Register": "註冊", + "DatabaseOptions": "數據庫選項", + "BackToPackagesPage": "回到包頁面", + "HowToInstall": "如何安裝", + "SeeOnNpm": "在NPM查看", + "SeeOnNuget": "在Nuget查看", + "MVCGulpCommandExplanation": "如果你使用MVC (Razor Pages) UI,在包安裝完成後運行 \"gulp\" 命令.", + "UsingABPCLI": "使用 Abp CLI", + "WithoutABPCLI": "不使用 ABP CLI", + "ABPCLIModuleDependency": "ABP CLI會自動添加模塊依賴.", + "AddModuleDependency": "然後添加模塊依賴", + "Packages": "包", + "NugetPackages": "Nuget包", + "NPMPackages": "NPM包", + "SeeDocs": "查看文檔", + "None": "空", + "Application": "應用程序", + "Module": "模塊", + "PackageName": "包名稱", + "LicenseURL": "許可URL", + "License": "許可", + "ProjectCreationSuccessMessage": "你的項目創建成功", + "HowToRunSolution": "如何運行你的解決方案?", + "GettingStartedMessage": "查看入門文檔了解如何配置和運行你的解決方案.", + "WebAppDevTutorial": "Web App 開發教程", + "WebAppDevTutorialMessage": "查看web應用程序開發教程文檔,一步一步的開發示例.", + "CommunityArticles": "社區文檔", + "CommunityArticleMessage": "查看ABP社區平臺來閱讀關於ABP框架的文檔.", + "InvestigateSolutionDetails": "調查解決方案細節", + "StartupTemplateDocumentationMessage": "查看應用程序啟動模板文檔來學習你的解決方案架構和結構.", + "ClientSideDevelopment": "客戶端部分開發", + "ClientSideDevelopmentDocumentationMessage": "查看{0}文檔來學習用戶頁面(客戶端部分)開發.", + "DatabaseProviderDocumentationMessage": "查看{0}文檔來學習用數據庫層開發.", + "ABPCommercialExplanationMessage": "ABP商業版為ABP框架提供了高級模塊,主題,工具和支持." } } \ No newline at end of file diff --git a/common.props b/common.props index 6454f01a25..a62f5b67b2 100644 --- a/common.props +++ b/common.props @@ -1,7 +1,7 @@ - latest - 4.3.1 + latest + 4.4.0 $(NoWarn);CS1591;CS0436 https://abp.io/assets/abp_nupkg.png https://abp.io/ diff --git a/docs/en/Authorization.md b/docs/en/Authorization.md index bd607b716e..6b906fe194 100644 --- a/docs/en/Authorization.md +++ b/docs/en/Authorization.md @@ -265,37 +265,7 @@ myGroup.AddPermission("Book_Creation") #### Creating a Custom Permission Dependency -Any class implements the `IPermissionStateProvider` interface can disable a permission based on a custom condition. - -**Example:** - -````csharp -public class MyCustomPermissionStateProvider : IPermissionStateProvider -{ - public Task IsEnabledAsync(PermissionStateContext context) - { - // You can implement your own logic here. - return Task.FromResult( - context.Permission.Name.StartsWith("Acme.BookStore")); - } -} -```` - -Then you can add `MyCustomPermissionStateProvider` to any permission definition, using the `AddStateProviders` extension method: - -````csharp -myGroup.AddPermission("Book_Creation") - .AddStateProviders(new MyCustomPermissionStateProvider()); -```` - -Or you can globally add your custom provider to make it working for all permissions: - -````csharp -Configure(options => -{ - options.GlobalStateProviders.Add(); -}); -```` +`PermissionDefinition` supports state check, Please refer to [Simple State Checker's documentation](SimpleStateChecker.md) ## IAuthorizationService diff --git a/docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/POST.md b/docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/POST.md index 50aab3559b..31946691ab 100644 --- a/docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/POST.md +++ b/docs/en/Blog-Posts/2021-03-31 v4_3 Commercial Preview/POST.md @@ -1,6 +1,6 @@ # ABP Commercial 4.3 RC Has Been Published -ABP Commercial version 4.3 RC (Release Candidate) has been published alongside ABP Framework 4.3. RC (TODO: link). I will introduce the new features in this blog post. Here, a list of highlights for this release; +ABP Commercial version 4.3 RC (Release Candidate) has been published alongside [ABP Framework 4.3. RC](https://blog.abp.io/abp/ABP-Framework-4.3-RC-Has-Been-Published). I will introduce the new features in this blog post. Here, a list of highlights for this release; * The **microservice starter template** is getting more mature. We've also added a **service template** to add new microservices to the solution. * New option for the application starter template to have a **separate database schema for tenant databases**. @@ -15,7 +15,7 @@ Here, some other features already covered in the ABP Framework announcement, but * **Email setting** management UI * **Module extensibility** system is now available for the **Blazor UI** too. -> This post doesn't cover the features and changes done on the ABP Framework side. Please also see the **ABP Framework 4.3. RC blog post** (TODO: link). +> This post doesn't cover the features and changes done on the ABP Framework side. Please also see the **[ABP Framework 4.3. RC blog post](https://blog.abp.io/abp/ABP-Framework-4.3-RC-Has-Been-Published)**. ## The Migration Guide @@ -69,7 +69,7 @@ Automatic migration only tries one time. If it fails, it writes the exception lo ### New Module: CMS Kit -CMS Kit module initial version has been released with this version. As stated in the ABP Framework 4.3 announcement post (TODO: link), it should be considered premature for now. +CMS Kit module initial version has been released with this version. As stated in the [ABP Framework 4.3 announcement post](https://blog.abp.io/abp/ABP-Framework-4.3-RC-Has-Been-Published), it should be considered premature for now. For ABP Commercial application startup template, we are providing an option to include the CMS Kit into the solution while creating new solutions: diff --git a/docs/en/Blog-Posts/2021-03-31 v4_3 Preview/POST.md b/docs/en/Blog-Posts/2021-03-31 v4_3 Preview/POST.md index cfb9bf0eed..e1e04e7a90 100644 --- a/docs/en/Blog-Posts/2021-03-31 v4_3 Preview/POST.md +++ b/docs/en/Blog-Posts/2021-03-31 v4_3 Preview/POST.md @@ -10,11 +10,11 @@ We are super excited to announce the ABP Framework 4.3 RC (Release Candidate). H * CLI support to easily add the **Basic Theme** into the solution. * New **IInitLogger** service to write logs before dependency injection phase completed. -Besides the new features above, we've done many performance improvements, enhancements and bug fixes on the current features. See the [4.3 milestone](https://github.com/abpframework/abp/milestone/49) on GitHub for all changes made on this version. +Besides the new features above, we've done many performance improvements, enhancements and bug fixes on the current features. See the [4.3 milestone](https://github.com/abpframework/abp/milestone/49?closed=1) on GitHub for all changes made on this version. -This version was a big development journey for us; [~160 issues](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3A4.3-preview) resolved, [~300 PRs](https://github.com/abpframework/abp/pulls?q=is%3Aopen+is%3Apr+milestone%3A4.3-preview) merged and **~1,700 commits** done only in the [main framework repository](https://github.com/abpframework/abp). **Thanks to the ABP Framework team and all the contributors.** +This version was a big development journey for us; [~160 issues](https://github.com/abpframework/abp/issues?q=is%3Aissue+milestone%3A4.3-preview+is%3Aclosed) resolved, [~300 PRs](https://github.com/abpframework/abp/issues?q=is%3Apr+milestone%3A4.3-preview+is%3Aclosed) merged and **~1,700 commits** done only in the [main framework repository](https://github.com/abpframework/abp). **Thanks to the ABP Framework team and all the contributors.** -> ABP Commercial 4.3 RC has also been published. We will write a separate blog post for it. +> ABP Commercial 4.3 RC has also been published. Check out [the commercial blog post](https://blog.abp.io/abp/ABP-Commercial-4.3-RC-Has-Been-Published). ## The Migration Guide @@ -63,7 +63,7 @@ CMS (Content Management System) Kit was a module we worked on for the last coupl * **Reactions**: Allows users to react to content via emojis, like a smile, upvote, downvote, etc. * **Rating**: This component is used to rate content by users. -All features are separately usable. For example, you can create an image gallery and reuse the Comments and Tags features for the images. You can enable/disable features individually using the [Global Features System](https://docs.abp.io/en/abp/4.3/global-features). +All features are separately usable. For example, you can create an image gallery and reuse the Comments and Tags features for the images. You can enable/disable features individually using the [Global Features System](https://docs.abp.io/en/abp/4.3/Global-Features). > We will create a separate blog post for the CMS Kit module, so I keep it short. diff --git a/docs/en/Blog-Posts/2021-04-05 CmsKit/POST.md b/docs/en/Blog-Posts/2021-04-05 CmsKit/POST.md index ad8b89faa0..740adb96c7 100644 --- a/docs/en/Blog-Posts/2021-04-05 CmsKit/POST.md +++ b/docs/en/Blog-Posts/2021-04-05 CmsKit/POST.md @@ -1,3 +1,85 @@ -# Introducing the CMS Kit Module for the ABP Framework +# Introducing The CMS-Kit Module + +One of the most exciting announcements of the ABP Framework 4.3 release was releasing the initial version of the CMS Kit module. The team had been working hard to release the initial version for months. For those who didn't read the [ABP Framework 4.3 release post](https://blog.abp.io/abp/ABP-Framework-4.3-RC-Has-Been-Published), the CMS Kit module adds CMS(Content Management System) capabilities to your application. Some of the CMS Kit features are open source and free, while others are only included in the Pro version included in the ABP Commercial. + +List of free and pro features in the CMS Kit module; + +- Free + - Page System: Provides a **page** management system to manage dynamic pages. + - Blog System: Provides a **blog** system to create blogs and publish posts. + - Tag System: Provides a **tag** system to tag any kind of resources, such as blog posts. + - Comment System: Provides a **comment** system to add comments feature to any type of resource, such as blog posts, products, etc. + - Reaction System: Provides a **reaction** system to add reactions to any type of resource, such as blog posts or comments, etc. + - Rating System: Provides a **rating** system to add ratings feature to any type of resource, such as comments, products, etc. +- Pro + - Newsletter System: Provides a **newsletter** system to allow users to subscribe to newsletters. + - Contact Form System: Provides a **contact form** system to allow users to write a message to you on public websites. + +## Installation + +CMS Kit module comes installed with commercial templates when you create the solution with the public website option. You can run the following command and create a solution with a public website. + +```bash +abp new Acme --with-public-website +``` + +If you're using the open-source version or adding the module to an existing project, the ABP CLI allows adding a module to a solution using `add-module` command. + +You can run the following command to add the module to an open-source solution. + +```bash +abp add-module Volo.CmsKit +``` + +If you're a commercial user, run the following command to install the pro version of the module. + +```bash +abp add-module Volo.CmsKit.Pro +``` + +After adding the module to the solution, you need to configure features. The CMS Kit module uses the [global feature](https://docs.abp.io/en/abp/latest/Global-Features) system for all features. To enable the features in the CMS Kit module, open the `GlobalFeatureConfigurator` class in the `Domain.Shared` project and place the following code to the `Configure` method to enable all features in the CMS kit module. + + ```csharp +GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit => +{ + cmsKit.EnableAll(); +}); + ``` + +If you're a commercial user, you need to enable CMS Kit Pro features as well. + +```csharp +GlobalFeatureManager.Instance.Modules.CmsKitPro(cmsKitPro => +{ + cmsKitPro.EnableAll(); +}); +``` + +> If you are using Entity Framework Core, do not forget to add a new migration and update your database after configuring the features. + +We've completed the installation step. Run the project, and you will see the CMS menu item in the menu. + +![cms-kit-menu](cms-kit-menu.png) + +> CMS Kit's initial release only supports the MVC UI. We're planning to add Angular and Blazor support in upcoming releases. + +## Package Structures + +CMS Kit is designed for various usage scenarios. When you visit [nuget.org](https://www.nuget.org/packages?q=Volo.CmsKit) or [abp.io](https://abp.io/packages?moduleName=Volo.CmsKit.Pro) to see the available CMS Kit packages, you will find out that packages have admin, public and unified versions. + +For example, + + - `Volo.CmsKit.Admin.Application`: Contains functionality required by admin websites. + - `Volo.CmsKit.Public.Application`: Contains functionality required by public websites. + - `Volo.CmsKit.Application` : Unified package dependent on both public and admin packages. + + If you want to separate admin and public website codes, you can use the admin and public packages. However, if you want to keep admin and public website codes in a shared project, you can use the unified packages to include admin and public packages. + +> It is recommended to use the unified packages instead of adding both admin and public packages. + + + +We've covered the initial features, installation and configuration steps in this post. You can read the [open-source](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit) and [commercial](https://docs.abp.io/en/commercial/latest/modules/CMS-Kit) documentation to get further information about features and the CMS Kit module. CMS Kit's initial version contains lots of features that you can easily integrate and use in your applications. We're planning to improve the existing features, fixing bugs and adding new features in upcoming releases. If you want to give some feedback or have a feature request, please reach out to us from [GitHub](https://github.com/abpframework/abp) or [support.abp.io](https://support.abp.io). We will be happy to plan the CMS Kit module's future together. + +Thank you! -TODO... \ No newline at end of file diff --git a/docs/en/Blog-Posts/2021-04-05 CmsKit/cms-kit-menu.png b/docs/en/Blog-Posts/2021-04-05 CmsKit/cms-kit-menu.png new file mode 100644 index 0000000000..3f187c9a9d Binary files /dev/null and b/docs/en/Blog-Posts/2021-04-05 CmsKit/cms-kit-menu.png differ diff --git a/docs/en/Blog-Posts/2021-04-26 v4_3_Release_Stable/POST.md b/docs/en/Blog-Posts/2021-04-26 v4_3_Release_Stable/POST.md new file mode 100644 index 0000000000..d06e2370e0 --- /dev/null +++ b/docs/en/Blog-Posts/2021-04-26 v4_3_Release_Stable/POST.md @@ -0,0 +1,53 @@ +# ABP.IO Platform 4.3 Final Has Been Released! + +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 4.3 versions have been released today. + +## What's New With 4.3? + +Since all the new features are already explained in details with the 4.3 RC announcement posts, I will not repeat all the details again. See the related blog posts for all the features and enhancements; + +* [What's New with the ABP Framework 4.3](https://blog.abp.io/abp/ABP-Framework-4.3-RC-Has-Been-Published) +* [What's new with the ABP Commercial 4.3](https://blog.abp.io/abp/ABP-Commercial-4.3-RC-Has-Been-Published) + +## The Quick Start Tutorial + +With this version, we've created a minimalist [quick start tutorial](https://docs.abp.io/en/abp/latest/Tutorials/Todo/Index) for developers who are new to the ABP Framework. + +## How to Upgrade an Existing Solution + +### Install/Update the ABP CLI + +First of all, install the ABP CLI or upgrade to the latest version. + +If you haven't installed yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update an existing installation: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +### ABP UPDATE Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guides + +**Check the migration guides ([for ABP Framework](https://docs.abp.io/en/abp/latest/Migration-Guides/Abp-4_3) & for [ABP Commercial](https://docs.abp.io/en/commercial/latest/migration-guides/v4_3)) for the applications with the version 4.2.x upgrading to the version 4.3.0.** + +## The Road Map + +The next feature version will be 4.4. It is planned to release the 4.4 RC (Release Candidate) at the end of Quarter 2, 2021. See the updated road maps; + +* [ABP Framework Road Map](https://docs.abp.io/en/abp/latest/Road-Map) +* [ABP Commercial Road Map](https://docs.abp.io/en/commercial/latest/road-map) \ No newline at end of file diff --git a/docs/en/CLI-New-Command-Samples.md b/docs/en/CLI-New-Command-Samples.md index eedf03353c..52ca533c81 100644 --- a/docs/en/CLI-New-Command-Samples.md +++ b/docs/en/CLI-New-Command-Samples.md @@ -126,6 +126,12 @@ Module are reusable sub applications used by your main project. Using ABP Module ```bash abp new Acme.IssueManagement -t module --no-ui ``` + +* Creates the module and adds it to your solution + + ```bash + abp new Acme.IssueManagement -t module --add-to-solution-file + ``` ## Create a solution from a specific version diff --git a/docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md b/docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md index 86f9774c7f..80141a32fe 100644 --- a/docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md +++ b/docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md @@ -18,7 +18,7 @@ Abp Framework offers startup templates to get into the work faster. We can creat `abp new CustomizeUserDemo` -> In this article, I will go through the MVC application, but it will work also in the [Angular](https://docs.abp.io/en/abp/latest/Getting-Started?UI=NG&DB=EF&Tiered=No) application. +> In this article, I will go through the MVC application, but it will work also in the [Angular](https://docs.abp.io/en/abp/latest/Getting-Started?UI=NG&DB=EF&Tiered=No), [Blazor Server](https://docs.abp.io/en/abp/latest/Getting-Started?UI=BlazorServer&DB=EF&Tiered=No), and [Blazor WebAssembly](https://docs.abp.io/en/abp/latest/Getting-Started?UI=Blazor&DB=EF&Tiered=No) application. After the download is finished, we can run **CustomizeUserDemo.DbMigrator** project to create the database migrations and seed the initial data (admin user, role, etc). Then we can run `CustomizeUserDemo.Web` to see that our application is working. @@ -78,7 +78,7 @@ public static class CustomizeUserDemoEfCoreEntityExtensionMappings nameof(AppUser.Title), (entityBuilder, propertyBuilder) => { - propertyBuilder.HasDefaultValue(); + propertyBuilder.HasDefaultValue(""); propertyBuilder.HasMaxLength(UserConsts.MaxTitleLength); } ).MapEfCoreProperty( diff --git a/docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md b/docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md index b36d83d0ba..076ceb3aa0 100644 --- a/docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md +++ b/docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md @@ -447,11 +447,12 @@ namespace EventOrganizer.Events public async Task> GetUpcomingAsync() { - var events = await AsyncExecuter.ToListAsync( - _eventRepository - .Where(x => x.StartTime > Clock.Now) - .OrderBy(x => x.StartTime) - ); + var queryable = await _eventRepository.GetQueryableAsync(); + var query = queryable + .Where(x => x.StartTime > Clock.Now) + .OrderBy(x => x.StartTime); + + var events = await AsyncExecuter.ToListAsync(query); return ObjectMapper.Map, List>(events); } @@ -653,11 +654,12 @@ namespace EventOrganizer.Events public async Task> GetUpcomingAsync() { - var events = await AsyncExecuter.ToListAsync( - _eventRepository - .Where(x => x.StartTime > Clock.Now) - .OrderBy(x => x.StartTime) - ); + var queryable = await _eventRepository.GetQueryableAsync(); + var query = queryable + .Where(x => x.StartTime > Clock.Now) + .OrderBy(x => x.StartTime); + + var events = await AsyncExecuter.ToListAsync(query); return ObjectMapper.Map, List>(events); } @@ -666,7 +668,12 @@ namespace EventOrganizer.Events { var @event = await _eventRepository.GetAsync(id); var attendeeIds = @event.Attendees.Select(a => a.UserId).ToList(); - var attendees = (await AsyncExecuter.ToListAsync(_userRepository.Where(u => attendeeIds.Contains(u.Id)))) + + var queryable = await _userRepository.GetQueryableAsync(); + var query = queryable + .Where(u => attendeeIds.Contains(u.Id)); + + var attendees = (await AsyncExecuter.ToListAsync(query)) .ToDictionary(x => x.Id); var result = ObjectMapper.Map(@event); diff --git a/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/POST.md b/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/POST.md index 7a88adde44..8aeff16612 100644 --- a/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/POST.md +++ b/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/POST.md @@ -38,8 +38,19 @@ Open `YourProjectWebModule.cs` class and add the following line to the `PreConfi #### 2- Add Client Scripts -2- In the `ConfigureServices` method of your web module add the following code to add the `signalr.js` and `notification-hub.js`. We'll add these packages in the next steps. +2- In the `ConfigureServices` method of your web module add the following code to add the `signalr.js` and `notification-hub.js`. We'll add these packages in the next steps. If you are not using Lepton Theme you can add the files to `StandardBundles.Scripts.Global`. +```csharp + Configure(options => + { + options + .ScriptBundles + .Get(LeptonThemeBundles.Scripts.Global) //or -> Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling.StandardBundles.Scripts.Global + .AddFiles("/libs/signalr/signalr.js") + .AddFiles("/Pages/notification-hub.js"); + }); + ``` + ![Script Bundles](add-script-bundles.jpg) #### 3- Add Hub Endpoint @@ -71,6 +82,11 @@ Add the following JavaScript class into your `Pages` folder in your Web project. Add [Microsoft.SignalR](https://www.npmjs.com/package/@microsoft/signalr) JavaScript package to the `package.json` which is located in your root folder of the Web project. After you add it, run `yarn` command in your Web directory to be able to install this package. +You can install the latest version (3.1.13 will be old) +``` + "@microsoft/signalr": "^3.1.13" +```` + ![Add SignalR package](signalr-package.jpg) #### 3- Add resource Mapping @@ -94,6 +110,8 @@ To do this replace the `Index.cshtml` and `Index.cshtml.cs` with the followings: #### 5- See it in action -Run your web project and in the Index page you'll see a button named as "Get Notification". Click the button and see the notification that comes from SignalR. This is a basic usage of SignalR notification system. You can implement it according to your own requirements. +Run your web project and in the Index page you'll Server Time will be updated every second. The time information comes from backend via SignalR. +This is a very basic usage of SignalR notification system. +You can implement your own SignalR notification system based on your requirements. ![Result](result.jpg) diff --git a/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/POST.md b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/POST.md new file mode 100644 index 0000000000..2e8fa867fb --- /dev/null +++ b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/POST.md @@ -0,0 +1,114 @@ +## Integrating SyncFusion UI with ABP Framework Blazor UI + +Hi, in this step by step article, I will show you how to integrate [Syncfusion](https://www.syncfusion.com/blazor-components), a blazor UI components into ABP Framework-based applications. + +![example-result](example-result.png) + +*(A screenshot from the example application developed in this article)* + +## Create the Project + +> First thing is to create the project. ABP Framework offers startup templates to get into business faster. + +In this article, I will create a new startup template with EF Core as a database provider and Blazor for UI framework. But if you already have a project with Blazor UI, you don't need to create a new startup template, you can directly implement the following steps to your existing project. + +> If you already have a project with the Blazor UI, you can skip this section. + +* Before starting the development, we will create a new solution named `SyncfusionSample` (or whatever you want). We will create a new startup template with EF Core as a database provider and Blazor for UI framework by using [ABP CLI](https://docs.abp.io/en/abp/latest/CLI): + +````bash +md SyncfusionSample +cd SyncfusionSample +```` + +After we have navigated inside of `SyncfusionSample` directory, we can create a new project. Note that I am creating Blazor Server (`blazor-server`) project. If you want to create a regular Blazor WebAssembly project just use `blazor` keyword instead. + +````bash +abp new SyncfusionSample -u blazor-server +```` + +and + +````bash +dotnet restore +```` + +* Our project boilerplate will be ready after the download is finished. Then, we can open the solution in the Visual Studio (or any other IDE) and run the `SyncfusionSample.DbMigrator` to create the database and seed initial data (which creates the admin user, admin role, permissions etc.) + +![initial-project](initial-project.png) + +* After database and initial data created, +* Run the `SyncfusionSample.Blazor` to see our UI working properly. + +> _Default login credentials for admin: username is **admin** and password is **1q2w3E\***_ + +## Install Syncfusion + +You can follow [this documentation](https://blazor.syncfusion.com/documentation/getting-started/blazor-server-side-visual-studio-2019/) to install Syncfusion packages into your computer. + +### Adding Syncfusion NuGet Packages + +Select `SyncfusionSample.Blazor` as the **default project** and then install NuGet packages. + +```bash +Install-Package Syncfusion.Blazor.Grid +``` + +### Register Syncfusion Resources + +1. Add the following line to the HEAD section of the `_Host.cshtml` file within the `SyncfusionSample.Blazor` project: + + ```Razor + + + + + ``` + +2. In the `SyncfusionSampleBlazorModule` class, call the `AddSyncfusionBlazor()` method from your project's `ConfigureServices()` method: + + ```csharp + public override void ConfigureServices(ServiceConfigurationContext context) + { + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var configuration = context.Services.GetConfiguration(); + + // ... + + context.Services.AddSyncfusionBlazor(); + Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("YOUR LICENSE KEY"); + } + ``` + + > To get the `LICENSE KEY` you can login into your Syncfusion account and request the key. Trial keys are also available. + +3. Register the **SyncfusionSample.Blazor** namespace(s) in the `_Imports.razor` file: + + ```Razor + @using Syncfusion.Blazor + @using Syncfusion.Blazor.Buttons + @using Syncfusion.Blazor.Inputs + @using Syncfusion.Blazor.Calendars + @using Syncfusion.Blazor.Popups + @using Syncfusion.Blazor.Grids + ``` + +## The Sample Application + +We have created a sample application with [SfGrid](https://blazor.syncfusion.com/documentation/datagrid/getting-started/) example. + +### The Source Code + +You can download the source code from [here](https://github.com/abpframework/abp-samples/tree/master/SyncfusionSample). + +The related files for this example are marked in the following screenshots. + +![table-app-contract](table-app-contract.png) + +![table-application](table-application.png) + +![table-web](table-web.png) + +## Conclusion + +In this article, I've explained how to use [Syncfusion](https://www.syncfusion.com/blazor-components) components in your application. ABP Framework is designed so that it can work with any UI library/framework. diff --git a/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/example-result.png b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/example-result.png new file mode 100644 index 0000000000..e773d100f0 Binary files /dev/null and b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/example-result.png differ diff --git a/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/initial-project.png b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/initial-project.png new file mode 100644 index 0000000000..eb28aacfe0 Binary files /dev/null and b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/initial-project.png differ diff --git a/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/table-app-contract.png b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/table-app-contract.png new file mode 100644 index 0000000000..be0accc721 Binary files /dev/null and b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/table-app-contract.png differ diff --git a/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/table-application.png b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/table-application.png new file mode 100644 index 0000000000..e2b552479d Binary files /dev/null and b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/table-application.png differ diff --git a/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/table-web.png b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/table-web.png new file mode 100644 index 0000000000..289ad0805b Binary files /dev/null and b/docs/en/Community-Articles/2021-04-22-How-to-Integrate-the-Syncfusion-Blazor-Component/table-web.png differ diff --git a/docs/en/Entity-Framework-Core.md b/docs/en/Entity-Framework-Core.md index 241a08790f..fcbf5d8091 100644 --- a/docs/en/Entity-Framework-Core.md +++ b/docs/en/Entity-Framework-Core.md @@ -724,7 +724,19 @@ One advantage of using an interface for a DbContext is then it will be replaceab ### Replace Other DbContextes -Once you properly define and use an interface for DbContext, then any other implementation can replace it using the `ReplaceDbContext` option: +Once you properly define and use an interface for DbContext, then any other implementation can use the following ways to replace it: + +**ReplaceDbContextAttribute** + +```csharp +[ReplaceDbContext(typeof(IBookStoreDbContext))] +public class OtherDbContext : AbpDbContext, IBookStoreDbContext +{ + //... +} +``` + +**ReplaceDbContext option** ````csharp context.Services.AddAbpDbContext(options => diff --git a/docs/en/MongoDB.md b/docs/en/MongoDB.md index 5bcdfe7730..d99c40da43 100644 --- a/docs/en/MongoDB.md +++ b/docs/en/MongoDB.md @@ -391,7 +391,19 @@ One advantage of using interface for a MongoDbContext is then it becomes replace #### Replace Other DbContextes -Once you properly define and use an interface for a MongoDbContext , then any other implementation can replace it using the `ReplaceDbContext` option: +Once you properly define and use an interface for a MongoDbContext , then any other implementation can use the following ways to replace it: + +**ReplaceDbContextAttribute** + +```csharp +[ReplaceDbContext(typeof(IBookStoreMongoDbContext))] +public class OtherMongoDbContext : AbpMongoDbContext, IBookStoreMongoDbContext +{ + //... +} +``` + +**ReplaceDbContext option** ```csharp context.Services.AddMongoDbContext(options => diff --git a/docs/en/SimpleStateChecker.md b/docs/en/SimpleStateChecker.md new file mode 100644 index 0000000000..584fef1592 --- /dev/null +++ b/docs/en/SimpleStateChecker.md @@ -0,0 +1,125 @@ +# Simple State Checker + +The simple state checking system can be used to enable/disable an object based on some dynamic conditions. For example, you can disable a menu item on the user interface, if the current user has not granted for a given permission. The simple state checking system provides a generic way to define and check such conditions. + +## Definition state checker. + +Any class can inherit `IHasSimpleStateCheckers` to support state checks. + +````csharp +public class MyObject : IHasSimpleStateCheckers +{ + public int Id { get; set; } + + public List> SimpleStateCheckers { get; } + + public MyObject() + { + SimpleStateCheckers = new List>(); + } +} +```` + +The `MyObject` class contains a collection of state checkers, you can add your custom checkers to it. + +````csharp +public class MyObjectStateChecker : ISimpleStateChecker +{ + public Task IsEnabledAsync(SimpleStateCheckerContext context) + { + var currentUser = context.ServiceProvider.GetRequiredService(); + return Task.FromResult(currentUser.IsInRole("Admin")); + } +} +```` + +````csharp +var myobj = new MyObject() +{ + Id = 100 +}; + +myobj.SimpleStateCheckers.Add(new MyObjectStateChecker()); +```` + +## Definition Global State Checkers + +`AbpSimpleStateCheckerOptions` is the options class that used to set the global state checkers for specific object. + +Example: Add global state for `MyObject`: + +````csharp +services.Configure>(options => +{ + options.GlobalSimpleStateCheckers.Add(); + //options.GlobalSimpleStateCheckers.Add<>(); //Add more global state checkers +}); +```` + +> Write this inside the `ConfigureServices` method of your module. + +## Check the state + +You can inject `ISimpleStateCheckerManager` service to check state. + +````csharp +bool enabled = await stateCheckerManager.IsEnabledAsync(myobj); +```` + +### Batch check the states + +If there are many instance items that require state checking, there may be performance problems. + +In this case, you can implement `ISimpleBatchStateChecker`. It can check multiple items at once. +You need to make sure that the same `ISimpleBatchStateChecker` instance is added to the `SimpleStateCheckers` of multiple instances. + +> `SimpleBatchStateCheckerBase` inherits the `ISimpleBatchStateChecker` interface and implements the `IsEnabledAsync` method of a single object by default. + +````csharp +public class MyObjectBatchStateChecker : SimpleBatchStateCheckerBase +{ + public override Task> IsEnabledAsync(SimpleBatchStateCheckerContext context) + { + var result = new SimpleStateCheckerResult(context.States); + + foreach (var myObject in context.States) + { + if (myObject.Id > 100) + { + result[myObject] = true; + } + } + + return Task.FromResult(result); + } +} +```` + +````csharp +var myobj1 = new MyObject() +{ + Id = 100 +}; +var myobj2 = new MyObject() +{ + Id = 99 +}; + +var myObjectBatchStateChecker = new MyObjectBatchStateChecker(); + +myobj1.SimpleStateCheckers.Add(myObjectBatchStateChecker); +myobj2.SimpleStateCheckers.Add(myObjectBatchStateChecker); + +SimpleStateCheckerResult stateCheckerResult = await stateCheckerManager.IsEnabledAsync(new []{ myobj1, myobj2 }); +```` + +## Built-in State Checkers + +The `PermissionDefinition`, `ApplicationMenuItem` and `ToolbarItem` objects have implemented state checks and have built-in general state checkers, you can directly use their extension methods. + +````csharp +RequireAuthenticated(); +RequirePermissions(bool requiresAll, params string[] permissions); +RequireFeatures(bool requiresAll, params string[] features); +RequireGlobalFeatures(bool requiresAll, params Type[] globalFeatures); +```` diff --git a/docs/en/Text-Templating-Razor.md b/docs/en/Text-Templating-Razor.md new file mode 100644 index 0000000000..44a207a991 --- /dev/null +++ b/docs/en/Text-Templating-Razor.md @@ -0,0 +1,578 @@ +# Razor Integration + + +The Razor template is a standard C# class, so you can freely use the functions of C#, such as `dependency injection`, using `LINQ`, custom methods, and even using `Repository`. + + +## Installation + +It is suggested to use the [ABP CLI](CLI.md) to install this package. + +### Using the ABP CLI + +Open a command line window in the folder of the project (.csproj file) and type the following command: + +````bash +abp add-package Volo.Abp.TextTemplating.Razor +```` + +### Manual Installation + +If you want to manually install; + +1. Add the [Volo.Abp.TextTemplating.Razor](https://www.nuget.org/packages/Volo.Abp.TextTemplating.Razor) NuGet package to your project: + +```` +Install-Package Volo.Abp.TextTemplating.Razor +```` + +2. Add the `AbpTextTemplatingRazorModule` to the dependency list of your module: + +````csharp +[DependsOn( + //...other dependencies + typeof(AbpTextTemplatingRazorModule) //Add the new module dependency + )] +public class YourModule : AbpModule +{ +} +```` + +## Add MetadataReference to CSharpCompilerOptions + +You need to add the `MetadataReference` of the type used in the template to `CSharpCompilerOptions's References`. + +````csharp +public override void ConfigureServices(ServiceConfigurationContext context) +{ + Configure(options => + { + options.References.Add(MetadataReference.CreateFromFile(typeof(YourModule).Assembly.Location)); + }); +} +```` + +## Add MetadataReference for a template. + +You can add some `MetadataReference` to the template + +````csharp +public override void ConfigureServices(ServiceConfigurationContext context) +{ + services.Configure(options => + { + //Hello is template name. + options.TemplateReferences.Add("Hello", new List() + { + Assembly.Load("Microsoft.Extensions.Logging.Abstractions"), + Assembly.Load("Microsoft.Extensions.Logging") + } + .Select(x => MetadataReference.CreateFromFile(x.Location)) + .ToList()); + }); +} +```` + +## Defining Templates + +Before rendering a template, you should define it. Create a class inheriting from the `TemplateDefinitionProvider` base class: + +````csharp +public class DemoTemplateDefinitionProvider : TemplateDefinitionProvider +{ + public override void Define(ITemplateDefinitionContext context) + { + context.Add( + new TemplateDefinition("Hello") //template name: "Hello" + .WithRazorEngine() + .WithVirtualFilePath( + "/Demos/Hello/Hello.cshtml", //template content path + isInlineLocalized: true + ) + ); + } +} +```` + +* `context` object is used to add new templates or get the templates defined by depended modules. Used `context.Add(...)` to define a new template. +* `TemplateDefinition` is the class represents a template. Each template must have a unique name (that will be used while you are rendering the template). +* `/Demos/Hello/Hello.cshtml` is the path of the template file. +* `isInlineLocalized` is used to declare if you are using a single template for all languages (`true`) or different templates for each language (`false`). See the Localization section below for more. +* `WithRenderEngine` method is used to set the render engine of the template. + +### The Template Base + +Every `cshtml` template page needs to inherit `RazorTemplatePageBase` or `RazorTemplatePageBase`. +There are some useful properties in the base class that can be used in templates. eg: `Localizer`, `ServiceProvider`. + +### The Template Content + +`WithVirtualFilePath` indicates that we are using the [Virtual File System](Virtual-File-System.md) to store the template content. Create a `Hello.cshtml` file inside your project and mark it as "**embedded resource**" on the properties window: + +![hello-template-razor](images/hello-template-razor.png) + +Example `Hello.cshtml` content is shown below: + +```` +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase +Hello @Model.Name +```` + +The `HelloModel` class is: +````csharp +namespace HelloModelNamespace +{ + public class HelloModel + { + public string Name { get; set; } + } +} +```` + +The [Virtual File System](Virtual-File-System.md) requires to add your files in the `ConfigureServices` method of your [module](Module-Development-Basics.md) class: + +````csharp +Configure(options => +{ + options.FileSets.AddEmbedded("TextTemplateDemo"); +}); +```` + +* `TextTemplateDemoModule` is the module class that you define your template in. +* `TextTemplateDemo` is the root namespace of your project. + +## Rendering the Template + +`ITemplateRenderer` service is used to render a template content. + +### Example: Rendering a Simple Template + +````csharp +public class HelloDemo : ITransientDependency +{ + private readonly ITemplateRenderer _templateRenderer; + + public HelloDemo(ITemplateRenderer templateRenderer) + { + _templateRenderer = templateRenderer; + } + + public async Task RunAsync() + { + var result = await _templateRenderer.RenderAsync( + "Hello", //the template name + new HelloModel + { + Name = "John" + } + ); + + Console.WriteLine(result); + } +} +```` + +* `HelloDemo` is a simple class that injects the `ITemplateRenderer` in its constructor and uses it inside the `RunAsync` method. +* `RenderAsync` gets two fundamental parameters: + * `templateName`: The name of the template to be rendered (`Hello` in this example). + * `model`: An object that is used as the `model` inside the template (a `HelloModel` object in this example). + +The result shown below for this example: + +````csharp +Hello John :) +```` +## Localization + +It is possible to localize a template content based on the current culture. There are two types of localization options described in the following sections. + +### Inline localization + +Inline localization uses the [localization system](Localization.md) to localize texts inside templates. + +#### Example: Reset Password Link + +Assuming you need to send an email to a user to reset her/his password. Here, the model/template content: + +````csharp +namespace ResetMyPasswordModelNamespace +{ + public class ResetMyPasswordModel + { + public string Link { get; set; } + + public string Name { get; set; } + } +} +```` + +````html +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase +@Localizer["ResetMyPassword", Model.Name] +```` + +`Localizer` service is used to localize the given key based on the current user culture. You need to define the `ResetMyPassword` key inside your localization file: + +````json +"ResetMyPasswordTitle": "Reset my password", +"ResetMyPassword": "Hi {0}, Click here to reset your password" +```` + +You also need to declare the localization resource to be used with this template, inside your template definition provider class: + +````csharp +context.Add( + new TemplateDefinition( + "PasswordReset", //Template name + typeof(DemoResource) //LOCALIZATION RESOURCE + ) + .WithRazorEngine() + .WithVirtualFilePath( + "/Demos/PasswordReset/PasswordReset.cshtml", //template content path + isInlineLocalized: true + ) +); +```` + +That's all. When you render this template like that: + +````csharp +var result = await _templateRenderer.RenderAsync( + "PasswordReset", //the template name + new PasswordResetModel + { + Name = "john", + Link = "https://abp.io/example-link?userId=123&token=ABC" + } +); +```` + +You will see the localized result: + +````html +Hi john, Click here to reset your password +```` + +> If you define the [default localization resource](Localization.md) for your application, then no need to declare the resource type for the template definition. + +### Multiple Contents Localization + +Instead of a single template that uses the localization system to localize the template, you may want to create different template files for each language. It can be needed if the template should be completely different for a specific culture rather than simple text localizations. + +#### Example: Welcome Email Template + +Assuming that you want to send a welcome email to your users, but want to define a completely different template based on the user culture. + +First, create a folder and put your templates inside it, like `en.cshtml`, `tr.cshtml`... one for each culture you support: + +![multiple-file-template-razor](images/multiple-file-template-razor.png) + +Then add your template definition in the template definition provider class: + +````csharp +context.Add( + new TemplateDefinition( + name: "WelcomeEmail", + defaultCultureName: "en" + ) + .WithRazorEngine() + .WithVirtualFilePath( + "/Demos/WelcomeEmail/Templates", //template content folder + isInlineLocalized: false + ) +); +```` + +* Set **default culture name**, so it fallbacks to the default culture if there is no template for the desired culture. +* Specify **the template folder** rather than a single template file. +* Set `isInlineLocalized` to `false` for this case. + +That's all, you can render the template for the current culture: + +````csharp +var result = await _templateRenderer.RenderAsync("WelcomeEmail"); +```` + +> Skipped the modal for this example to keep it simple, but you can use models as just explained before. + +### Specify the Culture + +`ITemplateRenderer` service uses the current culture (`CultureInfo.CurrentUICulture`) if not specified. If you need, you can specify the culture as the `cultureName` parameter: + +````csharp +var result = await _templateRenderer.RenderAsync( + "WelcomeEmail", + cultureName: "en" +); +```` + +## Layout Templates + +Layout templates are used to create shared layouts among other templates. It is similar to the layout system in the ASP.NET Core MVC / Razor Pages. + +### Example: Email HTML Layout Template + +For example, you may want to create a single layout for all of your email templates. + +First, create a template file just like before: + +````html +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase + + + + + + + @Body + + +```` + +* A layout template must have a `Body` part as a place holder for the rendered child content. + +The register your template in the template definition provider: + +````csharp +context.Add( + new TemplateDefinition( + "EmailLayout", + isLayout: true //SET isLayout! + ) + .WithRazorEngine() + .WithVirtualFilePath( + "/Demos/EmailLayout/EmailLayout.cshtml", + isInlineLocalized: true + ) +); +```` + +Now, you can use this template as the layout of any other template: + +````csharp +context.Add( + new TemplateDefinition( + name: "WelcomeEmail", + defaultCultureName: "en", + layout: "EmailLayout" //Set the LAYOUT + ) + .WithRazorEngine() + .WithVirtualFilePath( + "/Demos/WelcomeEmail/Templates", + isInlineLocalized: false + ) +); +```` + +## Global Context + +ABP passes the `model` that can be used to access to the model inside the template. You can pass more global variables if you need. + +An example template content: + +````html +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase +A global object value: @GlobalContext["myGlobalObject"] +```` + +This template assumes that that is a `myGlobalObject` object in the template rendering context. You can provide it like shown below: + +````csharp +var result = await _templateRenderer.RenderAsync( + "GlobalContextUsage", + globalContext: new Dictionary + { + {"myGlobalObject", "TEST VALUE"} + } +); +```` + +The rendering result will be: + +```` +A global object value: TEST VALUE +```` + +## Replacing the Existing Templates + +It is possible to replace a template defined by a module that used in your application. In this way, you can customize the templates based on your requirements without changing the module code. + +### Option-1: Using the Virtual File System + +The [Virtual File System](Virtual-File-System.md) allows you to override any file by placing the same file into the same path in your project. + +#### Example: Replace the Standard Email Layout Template + +ABP Framework provides an [email sending system](Emailing.md) that internally uses the text templating to render the email content. It defines a standard email layout template in the `/Volo/Abp/Emailing/Templates/Layout.cshtml` path. The unique name of the template is `Abp.StandardEmailTemplates.Layout` and this string is defined as a constant on the `Volo.Abp.Emailing.Templates.StandardEmailTemplates` static class. + +Do the following steps to replace the template file with your own; + +**1)** Add a new file into the same location (`/Volo/Abp/Emailing/Templates/Layout.cshtml`) in your project: + +![replace-email-layout-razor](images/replace-email-layout-razor.png) + +**2)** Prepare your email layout template: + +````html +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase + + + + + + +

This my header

+ + @Body + +
+ This is my footer... +
+ + +```` + +This example simply adds a header and footer to the template and renders the content between them (see the *Layout Templates* section above to understand it). + +**3)** Configure the embedded resources in the `.csproj` file + +* Add [Microsoft.Extensions.FileProviders.Embedded](https://www.nuget.org/packages/Microsoft.Extensions.FileProviders.Embedded) NuGet package to the project. +* Add `true` into the `...` section of your `.csproj` file. +* Add the following code into your `.csproj` file: + +````xml + + + + +```` + +This makes the template files "embedded resource". + +**4)** Configure the virtual file system + +Configure the `AbpVirtualFileSystemOptions` in the `ConfigureServices` method of your [module](Module-Development-Basics.md) to add the embedded files into the virtual file system: + +```csharp +Configure(options => +{ + options.FileSets.AddEmbedded(); +}); +``` + +`BookStoreDomainModule` should be your module name, in this example code. + +> Be sure that your module (directly or indirectly) [depends on](Module-Development-Basics.md) the `AbpEmailingModule`. Because the VFS can override files based on the dependency order. + +Now, your template will be used when you want to render the email layout template. + +### Option-2: Using the Template Definition Provider + +You can create a template definition provider class that gets the email layout template and changes the virtual file path for the template. + +**Example: Use the `/MyTemplates/EmailLayout.cshtml` file instead of the standard template** + +```csharp +using Volo.Abp.DependencyInjection; +using Volo.Abp.Emailing.Templates; +using Volo.Abp.TextTemplating; + +namespace MyProject +{ + public class MyTemplateDefinitionProvider + : TemplateDefinitionProvider, ITransientDependency + { + public override void Define(ITemplateDefinitionContext context) + { + var emailLayoutTemplate = context.GetOrNull(StandardEmailTemplates.Layout); + + emailLayoutTemplate + .WithVirtualFilePath( + "/MyTemplates/EmailLayout.cshtml", + isInlineLocalized: true + ); + } + } +} +``` + +You should still add the file `/MyTemplates/EmailLayout.cshtml` to the virtual file system as explained before. This approach allows you to locate templates in any folder instead of the folder defined by the depended module. + +Beside the template content, you can manipulate the template definition properties, like `DisplayName`, `Layout` or `LocalizationSource`. + +## Advanced Features + +This section covers some internals and more advanced usages of the text templating system. + +### Template Content Provider + +`ITemplateRenderer` is used to render the template, which is what you want for most of the cases. However, you can use the `ITemplateContentProvider` to get the raw (not rendered) template contents. + +> `ITemplateContentProvider` is internally used by the `ITemplateRenderer` to get the raw template contents. + +Example: + +````csharp +public class TemplateContentDemo : ITransientDependency +{ + private readonly ITemplateContentProvider _templateContentProvider; + + public TemplateContentDemo(ITemplateContentProvider templateContentProvider) + { + _templateContentProvider = templateContentProvider; + } + + public async Task RunAsync() + { + var result = await _templateContentProvider + .GetContentOrNullAsync("Hello"); + + Console.WriteLine(result); + } +} +```` + +The result will be the raw template content: + +```` +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase +Hello @Model.Name +```` + +* `GetContentOrNullAsync` returns `null` if no content defined for the requested template. +* It can get a `cultureName` parameter that is used if template has different files for different cultures (see Multiple Contents Localization section above). + +### Template Content Contributor + +`ITemplateContentProvider` service uses `ITemplateContentContributor` implementations to find template contents. There is a single pre-implemented content contributor, `VirtualFileTemplateContentContributor`, which gets template contents from the virtual file system as described above. + +You can implement the `ITemplateContentContributor` to read raw template contents from another source. + +Example: + +````csharp +public class MyTemplateContentProvider + : ITemplateContentContributor, ITransientDependency +{ + public async Task GetOrNullAsync(TemplateContentContributorContext context) + { + var templateName = context.TemplateDefinition.Name; + + //TODO: Try to find content from another source + return null; + } +} + +```` + +Return `null` if your source can not find the content, so `ITemplateContentProvider` fallbacks to the next contributor. + +### Template Definition Manager + +`ITemplateDefinitionManager` service can be used to get the template definitions (created by the template definition providers). + +## See Also + +* [The source code of the sample application](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo) developed and referred through this document. +* [Localization system](Localization.md). +* [Virtual File System](Virtual-File-System.md). diff --git a/docs/en/Text-Templating-Scriban.md b/docs/en/Text-Templating-Scriban.md new file mode 100644 index 0000000000..51b6c50f88 --- /dev/null +++ b/docs/en/Text-Templating-Scriban.md @@ -0,0 +1,526 @@ +# Razor Integration + +## Installation + +It is suggested to use the [ABP CLI](CLI.md) to install this package. + +### Using the ABP CLI + +Open a command line window in the folder of the project (.csproj file) and type the following command: + +````bash +abp add-package Volo.Abp.TextTemplating.Scriban +```` + +### Manual Installation + +If you want to manually install; + +1. Add the [Volo.Abp.TextTemplating.Scriban](https://www.nuget.org/packages/Volo.Abp.TextTemplating.Scriban) NuGet package to your project: + +```` +Install-Package Volo.Abp.TextTemplating.Scriban +```` + +2. Add the `AbpTextTemplatingScribanModule` to the dependency list of your module: + +````csharp +[DependsOn( + //...other dependencies + typeof(AbpTextTemplatingScribanModule) //Add the new module dependency + )] +public class YourModule : AbpModule +{ +} +```` + +## Defining Templates + +Before rendering a template, you should define it. Create a class inheriting from the `TemplateDefinitionProvider` base class: + +````csharp +public class DemoTemplateDefinitionProvider : TemplateDefinitionProvider +{ + public override void Define(ITemplateDefinitionContext context) + { + context.Add( + new TemplateDefinition("Hello") //template name: "Hello" + .WithVirtualFilePath( + "/Demos/Hello/Hello.tpl", //template content path + isInlineLocalized: true + ) + .WithScribanEngine() + ); + } +} +```` + +* `context` object is used to add new templates or get the templates defined by depended modules. Used `context.Add(...)` to define a new template. +* `TemplateDefinition` is the class represents a template. Each template must have a unique name (that will be used while you are rendering the template). +* `/Demos/Hello/Hello.tpl` is the path of the template file. +* `isInlineLocalized` is used to declare if you are using a single template for all languages (`true`) or different templates for each language (`false`). See the Localization section below for more. +* `WithRenderEngine` method is used to set the render engine of the template. + +### The Template Content + +`WithVirtualFilePath` indicates that we are using the [Virtual File System](Virtual-File-System.md) to store the template content. Create a `Hello.tpl` file inside your project and mark it as "**embedded resource**" on the properties window: + +![hello-template](images/hello-template.png) + +Example `Hello.tpl` content is shown below: + +```` +Hello {%{{{model.name}}}%} :) +```` + +The [Virtual File System](Virtual-File-System.md) requires to add your files in the `ConfigureServices` method of your [module](Module-Development-Basics.md) class: + +````csharp +Configure(options => +{ + options.FileSets.AddEmbedded("TextTemplateDemo"); +}); +```` + +* `TextTemplateDemoModule` is the module class that you define your template in. +* `TextTemplateDemo` is the root namespace of your project. + +## Rendering the Template + +`ITemplateRenderer` service is used to render a template content. + +### Example: Rendering a Simple Template + +````csharp +public class HelloDemo : ITransientDependency +{ + private readonly ITemplateRenderer _templateRenderer; + + public HelloDemo(ITemplateRenderer templateRenderer) + { + _templateRenderer = templateRenderer; + } + + public async Task RunAsync() + { + var result = await _templateRenderer.RenderAsync( + "Hello", //the template name + new HelloModel + { + Name = "John" + } + ); + + Console.WriteLine(result); + } +} +```` + +* `HelloDemo` is a simple class that injects the `ITemplateRenderer` in its constructor and uses it inside the `RunAsync` method. +* `RenderAsync` gets two fundamental parameters: + * `templateName`: The name of the template to be rendered (`Hello` in this example). + * `model`: An object that is used as the `model` inside the template (a `HelloModel` object in this example). + +The result shown below for this example: + +````csharp +Hello John :) +```` + +### Anonymous Model + +While it is suggested to create model classes for the templates, it would be practical (and possible) to use anonymous objects for simple cases: + +````csharp +var result = await _templateRenderer.RenderAsync( + "Hello", + new + { + Name = "John" + } +); +```` + +In this case, we haven't created a model class, but created an anonymous object as the model. + +### PascalCase vs snake_case + +PascalCase property names (like `UserName`) is used as snake_case (like `user_name`) in the templates. + +## Localization + +It is possible to localize a template content based on the current culture. There are two types of localization options described in the following sections. + +### Inline localization + +Inline localization uses the [localization system](Localization.md) to localize texts inside templates. + +#### Example: Reset Password Link + +Assuming you need to send an email to a user to reset her/his password. Here, the template content: + +```` +{%{{{L "ResetMyPassword" model.name}}}%} +```` + +`L` function is used to localize the given key based on the current user culture. You need to define the `ResetMyPassword` key inside your localization file: + +````json +"ResetMyPasswordTitle": "Reset my password", +"ResetMyPassword": "Hi {0}, Click here to reset your password" +```` + +You also need to declare the localization resource to be used with this template, inside your template definition provider class: + +````csharp +context.Add( + new TemplateDefinition( + "PasswordReset", //Template name + typeof(DemoResource) //LOCALIZATION RESOURCE + ) + .WithScribanEngine() + .WithVirtualFilePath( + "/Demos/PasswordReset/PasswordReset.tpl", //template content path + isInlineLocalized: true + ) +); +```` + +That's all. When you render this template like that: + +````csharp +var result = await _templateRenderer.RenderAsync( + "PasswordReset", //the template name + new PasswordResetModel + { + Name = "john", + Link = "https://abp.io/example-link?userId=123&token=ABC" + } +); +```` + +You will see the localized result: + +````csharp +Hi john, Click here to reset your password +```` + +> If you define the [default localization resource](Localization.md) for your application, then no need to declare the resource type for the template definition. + +### Multiple Contents Localization + +Instead of a single template that uses the localization system to localize the template, you may want to create different template files for each language. It can be needed if the template should be completely different for a specific culture rather than simple text localizations. + +#### Example: Welcome Email Template + +Assuming that you want to send a welcome email to your users, but want to define a completely different template based on the user culture. + +First, create a folder and put your templates inside it, like `en.tpl`, `tr.tpl`... one for each culture you support: + +![multiple-file-template](images/multiple-file-template.png) + +Then add your template definition in the template definition provider class: + +````csharp +context.Add( + new TemplateDefinition( + name: "WelcomeEmail", + defaultCultureName: "en" + ) + .WithScribanEngine() + .WithVirtualFilePath( + "/Demos/WelcomeEmail/Templates", //template content folder + isInlineLocalized: false + ) +); +```` + +* Set **default culture name**, so it fallbacks to the default culture if there is no template for the desired culture. +* Specify **the template folder** rather than a single template file. +* Set `isInlineLocalized` to `false` for this case. + +That's all, you can render the template for the current culture: + +````csharp +var result = await _templateRenderer.RenderAsync("WelcomeEmail"); +```` + +> Skipped the modal for this example to keep it simple, but you can use models as just explained before. + +### Specify the Culture + +`ITemplateRenderer` service uses the current culture (`CultureInfo.CurrentUICulture`) if not specified. If you need, you can specify the culture as the `cultureName` parameter: + +````csharp +var result = await _templateRenderer.RenderAsync( + "WelcomeEmail", + cultureName: "en" +); +```` + +## Layout Templates + +Layout templates are used to create shared layouts among other templates. It is similar to the layout system in the ASP.NET Core MVC / Razor Pages. + +### Example: Email HTML Layout Template + +For example, you may want to create a single layout for all of your email templates. + +First, create a template file just like before: + +````xml + + + + + + + {%{{{content}}}%} + + +```` + +* A layout template must have a **{%{{{content}}}%}** part as a place holder for the rendered child content. + +The register your template in the template definition provider: + +````csharp +context.Add( + new TemplateDefinition( + "EmailLayout", + isLayout: true //SET isLayout! + ) + .WithScribanEngine() + .WithVirtualFilePath( + "/Demos/EmailLayout/EmailLayout.tpl", + isInlineLocalized: true + ) +); +```` + +Now, you can use this template as the layout of any other template: + +````csharp +context.Add( + new TemplateDefinition( + name: "WelcomeEmail", + defaultCultureName: "en", + layout: "EmailLayout" //Set the LAYOUT + ) + .WithScribanEngine() + .WithVirtualFilePath( + "/Demos/WelcomeEmail/Templates", + isInlineLocalized: false + ) +); +```` + +## Global Context + +ABP passes the `model` that can be used to access to the model inside the template. You can pass more global variables if you need. + +An example template content: + +```` +A global object value: {%{{{myGlobalObject}}}%} +```` + +This template assumes that that is a `myGlobalObject` object in the template rendering context. You can provide it like shown below: + +````csharp +var result = await _templateRenderer.RenderAsync( + "GlobalContextUsage", + globalContext: new Dictionary + { + {"myGlobalObject", "TEST VALUE"} + } +); +```` + +The rendering result will be: + +```` +A global object value: TEST VALUE +```` + +## Replacing the Existing Templates + +It is possible to replace a template defined by a module that used in your application. In this way, you can customize the templates based on your requirements without changing the module code. + +### Option-1: Using the Virtual File System + +The [Virtual File System](Virtual-File-System.md) allows you to override any file by placing the same file into the same path in your project. + +#### Example: Replace the Standard Email Layout Template + +ABP Framework provides an [email sending system](Emailing.md) that internally uses the text templating to render the email content. It defines a standard email layout template in the `/Volo/Abp/Emailing/Templates/Layout.tpl` path. The unique name of the template is `Abp.StandardEmailTemplates.Layout` and this string is defined as a constant on the `Volo.Abp.Emailing.Templates.StandardEmailTemplates` static class. + +Do the following steps to replace the template file with your own; + +**1)** Add a new file into the same location (`/Volo/Abp/Emailing/Templates/Layout.tpl`) in your project: + +![replace-email-layout](images/replace-email-layout.png) + +**2)** Prepare your email layout template: + +````html + + + + + + +

This my header

+ + {%{{{content}}}%} + +
+ This is my footer... +
+ + +```` + +This example simply adds a header and footer to the template and renders the content between them (see the *Layout Templates* section above to understand it). + +**3)** Configure the embedded resources in the `.csproj` file + +* Add [Microsoft.Extensions.FileProviders.Embedded](https://www.nuget.org/packages/Microsoft.Extensions.FileProviders.Embedded) NuGet package to the project. +* Add `true` into the `...` section of your `.csproj` file. +* Add the following code into your `.csproj` file: + +````xml + + + + +```` + +This makes the template files "embedded resource". + +**4)** Configure the virtual file system + +Configure the `AbpVirtualFileSystemOptions` in the `ConfigureServices` method of your [module](Module-Development-Basics.md) to add the embedded files into the virtual file system: + +```csharp +Configure(options => +{ + options.FileSets.AddEmbedded(); +}); +``` + +`BookStoreDomainModule` should be your module name, in this example code. + +> Be sure that your module (directly or indirectly) [depends on](Module-Development-Basics.md) the `AbpEmailingModule`. Because the VFS can override files based on the dependency order. + +Now, your template will be used when you want to render the email layout template. + +### Option-2: Using the Template Definition Provider + +You can create a template definition provider class that gets the email layout template and changes the virtual file path for the template. + +**Example: Use the `/MyTemplates/EmailLayout.tpl` file instead of the standard template** + +```csharp +using Volo.Abp.DependencyInjection; +using Volo.Abp.Emailing.Templates; +using Volo.Abp.TextTemplating; + +namespace MyProject +{ + public class MyTemplateDefinitionProvider + : TemplateDefinitionProvider, ITransientDependency + { + public override void Define(ITemplateDefinitionContext context) + { + var emailLayoutTemplate = context.GetOrNull(StandardEmailTemplates.Layout); + + emailLayoutTemplate + .WithVirtualFilePath( + "/MyTemplates/EmailLayout.tpl", + isInlineLocalized: true + ); + } + } +} +``` + +You should still add the file `/MyTemplates/EmailLayout.tpl` to the virtual file system as explained before. This approach allows you to locate templates in any folder instead of the folder defined by the depended module. + +Beside the template content, you can manipulate the template definition properties, like `DisplayName`, `Layout` or `LocalizationSource`. + +## Advanced Features + +This section covers some internals and more advanced usages of the text templating system. + +### Template Content Provider + +`ITemplateRenderer` is used to render the template, which is what you want for most of the cases. However, you can use the `ITemplateContentProvider` to get the raw (not rendered) template contents. + +> `ITemplateContentProvider` is internally used by the `ITemplateRenderer` to get the raw template contents. + +Example: + +````csharp +public class TemplateContentDemo : ITransientDependency +{ + private readonly ITemplateContentProvider _templateContentProvider; + + public TemplateContentDemo(ITemplateContentProvider templateContentProvider) + { + _templateContentProvider = templateContentProvider; + } + + public async Task RunAsync() + { + var result = await _templateContentProvider + .GetContentOrNullAsync("Hello"); + + Console.WriteLine(result); + } +} +```` + +The result will be the raw template content: + +```` +Hello {%{{{model.name}}}%} :) +```` + +* `GetContentOrNullAsync` returns `null` if no content defined for the requested template. +* It can get a `cultureName` parameter that is used if template has different files for different cultures (see Multiple Contents Localization section above). + +### Template Content Contributor + +`ITemplateContentProvider` service uses `ITemplateContentContributor` implementations to find template contents. There is a single pre-implemented content contributor, `VirtualFileTemplateContentContributor`, which gets template contents from the virtual file system as described above. + +You can implement the `ITemplateContentContributor` to read raw template contents from another source. + +Example: + +````csharp +public class MyTemplateContentProvider + : ITemplateContentContributor, ITransientDependency +{ + public async Task GetOrNullAsync(TemplateContentContributorContext context) + { + var templateName = context.TemplateDefinition.Name; + + //TODO: Try to find content from another source + return null; + } +} + +```` + +Return `null` if your source can not find the content, so `ITemplateContentProvider` fallbacks to the next contributor. + +### Template Definition Manager + +`ITemplateDefinitionManager` service can be used to get the template definitions (created by the template definition providers). + +## See Also + +* [The source code of the sample application](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo) developed and referred through this document. +* [Localization system](Localization.md). +* [Virtual File System](Virtual-File-System.md). diff --git a/docs/en/Text-Templating.md b/docs/en/Text-Templating.md index bdea7cd00b..47e6c4cc80 100644 --- a/docs/en/Text-Templating.md +++ b/docs/en/Text-Templating.md @@ -12,552 +12,26 @@ It is very similar to an ASP.NET Core Razor View (or Page): You can use the rendered output for any purpose, like sending emails or preparing some reports. -### Example - -Here, a simple template: - -```` -Hello {%{{{model.name}}}%} :) -```` - -You can define a class with a `Name` property to render this template: - -````csharp -public class HelloModel -{ - public string Name { get; set; } -} -```` - -If you render the template with a `HelloModel` with the `Name` is `John`, the rendered output is will be: - -```` -Hello John :) -```` - Template rendering engine is very powerful; -* It is based on the [Scriban](https://github.com/lunet-io/scriban) library, so it supports **conditional logics**, **loops** and much more. +* It supports **conditional logics**, **loops** and much more. * Template content **can be localized**. * You can define **layout templates** to be used as the layout while rendering other templates. * You can pass arbitrary objects to the template context (beside the model) for advanced scenarios. -### Source Code - -Get [the source code of the sample application](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo) developed and referred through this document. - -## Installation - -It is suggested to use the [ABP CLI](CLI.md) to install this package. - -### Using the ABP CLI - -Open a command line window in the folder of the project (.csproj file) and type the following command: - -````bash -abp add-package Volo.Abp.TextTemplating -```` - -### Manual Installation - -If you want to manually install; - -1. Add the [Volo.Abp.TextTemplating](https://www.nuget.org/packages/Volo.Abp.TextTemplating) NuGet package to your project: - -```` -Install-Package Volo.Abp.TextTemplating -```` - -2. Add the `AbpTextTemplatingModule` to the dependency list of your module: - -````csharp -[DependsOn( - //...other dependencies - typeof(AbpTextTemplatingModule) //Add the new module dependency - )] -public class YourModule : AbpModule -{ -} -```` - -## Defining Templates - -Before rendering a template, you should define it. Create a class inheriting from the `TemplateDefinitionProvider` base class: - -````csharp -public class DemoTemplateDefinitionProvider : TemplateDefinitionProvider -{ - public override void Define(ITemplateDefinitionContext context) - { - context.Add( - new TemplateDefinition("Hello") //template name: "Hello" - .WithVirtualFilePath( - "/Demos/Hello/Hello.tpl", //template content path - isInlineLocalized: true - ) - ); - } -} -```` - -* `context` object is used to add new templates or get the templates defined by depended modules. Used `context.Add(...)` to define a new template. -* `TemplateDefinition` is the class represents a template. Each template must have a unique name (that will be used while you are rendering the template). -* `/Demos/Hello/Hello.tpl` is the path of the template file. -* `isInlineLocalized` is used to declare if you are using a single template for all languages (`true`) or different templates for each language (`false`). See the Localization section below for more. - -### The Template Content - -`WithVirtualFilePath` indicates that we are using the [Virtual File System](Virtual-File-System.md) to store the template content. Create a `Hello.tpl` file inside your project and mark it as "**embedded resource**" on the properties window: - -![hello-template](images/hello-template.png) - -Example `Hello.tpl` content is shown below: - -```` -Hello {%{{{model.name}}}%} :) -```` - -The [Virtual File System](Virtual-File-System.md) requires to add your files in the `ConfigureServices` method of your [module](Module-Development-Basics.md) class: - -````csharp -Configure(options => -{ - options.FileSets.AddEmbedded("TextTemplateDemo"); -}); -```` - -* `TextTemplateDemoModule` is the module class that you define your template in. -* `TextTemplateDemo` is the root namespace of your project. - -## Rendering the Template - -`ITemplateRenderer` service is used to render a template content. - -### Example: Rendering a Simple Template - -````csharp -public class HelloDemo : ITransientDependency -{ - private readonly ITemplateRenderer _templateRenderer; - - public HelloDemo(ITemplateRenderer templateRenderer) - { - _templateRenderer = templateRenderer; - } - - public async Task RunAsync() - { - var result = await _templateRenderer.RenderAsync( - "Hello", //the template name - new HelloModel - { - Name = "John" - } - ); - - Console.WriteLine(result); - } -} -```` - -* `HelloDemo` is a simple class that injects the `ITemplateRenderer` in its constructor and uses it inside the `RunAsync` method. -* `RenderAsync` gets two fundamental parameters: - * `templateName`: The name of the template to be rendered (`Hello` in this example). - * `model`: An object that is used as the `model` inside the template (a `HelloModel` object in this example). - -The result shown below for this example: - -````csharp -Hello John :) -```` - -### Anonymous Model - -While it is suggested to create model classes for the templates, it would be practical (and possible) to use anonymous objects for simple cases: - -````csharp -var result = await _templateRenderer.RenderAsync( - "Hello", - new - { - Name = "John" - } -); -```` - -In this case, we haven't created a model class, but created an anonymous object as the model. - -### PascalCase vs snake_case - -PascalCase property names (like `UserName`) is used as snake_case (like `user_name`) in the templates. - -## Localization - -It is possible to localize a template content based on the current culture. There are two types of localization options described in the following sections. - -### Inline localization - -Inline localization uses the [localization system](Localization.md) to localize texts inside templates. - -#### Example: Reset Password Link - -Assuming you need to send an email to a user to reset her/his password. Here, the template content: - -```` -{%{{{L "ResetMyPassword" model.name}}}%} -```` - -`L` function is used to localize the given key based on the current user culture. You need to define the `ResetMyPassword` key inside your localization file: - -````json -"ResetMyPasswordTitle": "Reset my password", -"ResetMyPassword": "Hi {0}, Click here to reset your password" -```` - -You also need to declare the localization resource to be used with this template, inside your template definition provider class: - -````csharp -context.Add( - new TemplateDefinition( - "PasswordReset", //Template name - typeof(DemoResource) //LOCALIZATION RESOURCE - ).WithVirtualFilePath( - "/Demos/PasswordReset/PasswordReset.tpl", //template content path - isInlineLocalized: true - ) -); -```` - -That's all. When you render this template like that: - -````csharp -var result = await _templateRenderer.RenderAsync( - "PasswordReset", //the template name - new PasswordResetModel - { - Name = "john", - Link = "https://abp.io/example-link?userId=123&token=ABC" - } -); -```` - -You will see the localized result: - -````csharp -Hi john, Click here to reset your password -```` - -> If you define the [default localization resource](Localization.md) for your application, then no need to declare the resource type for the template definition. - -### Multiple Contents Localization - -Instead of a single template that uses the localization system to localize the template, you may want to create different template files for each language. It can be needed if the template should be completely different for a specific culture rather than simple text localizations. - -#### Example: Welcome Email Template - -Assuming that you want to send a welcome email to your users, but want to define a completely different template based on the user culture. - -First, create a folder and put your templates inside it, like `en.tpl`, `tr.tpl`... one for each culture you support: - -![multiple-file-template](images/multiple-file-template.png) - -Then add your template definition in the template definition provider class: - -````csharp -context.Add( - new TemplateDefinition( - name: "WelcomeEmail", - defaultCultureName: "en" - ) - .WithVirtualFilePath( - "/Demos/WelcomeEmail/Templates", //template content folder - isInlineLocalized: false - ) -); -```` - -* Set **default culture name**, so it fallbacks to the default culture if there is no template for the desired culture. -* Specify **the template folder** rather than a single template file. -* Set `isInlineLocalized` to `false` for this case. - -That's all, you can render the template for the current culture: - -````csharp -var result = await _templateRenderer.RenderAsync("WelcomeEmail"); -```` +ABP Framework provides two templating engines; -> Skipped the modal for this example to keep it simple, but you can use models as just explained before. +* **[Razor](Text-Templating-Razor.md)** +* **[Scriban](Text-Templating-Scriban.md)** -### Specify the Culture +You can use different template engines in the same application, or even create a new custom template engine. -`ITemplateRenderer` service uses the current culture (`CultureInfo.CurrentUICulture`) if not specified. If you need, you can specify the culture as the `cultureName` parameter: +## Source Code -````csharp -var result = await _templateRenderer.RenderAsync( - "WelcomeEmail", - cultureName: "en" -); -```` - -## Layout Templates - -Layout templates are used to create shared layouts among other templates. It is similar to the layout system in the ASP.NET Core MVC / Razor Pages. - -### Example: Email HTML Layout Template - -For example, you may want to create a single layout for all of your email templates. - -First, create a template file just like before: - -````xml - - - - - - - {%{{{content}}}%} - - -```` - -* A layout template must have a **{%{{{content}}}%}** part as a place holder for the rendered child content. - -The register your template in the template definition provider: - -````csharp -context.Add( - new TemplateDefinition( - "EmailLayout", - isLayout: true //SET isLayout! - ).WithVirtualFilePath( - "/Demos/EmailLayout/EmailLayout.tpl", - isInlineLocalized: true - ) -); -```` - -Now, you can use this template as the layout of any other template: - -````csharp -context.Add( - new TemplateDefinition( - name: "WelcomeEmail", - defaultCultureName: "en", - layout: "EmailLayout" //Set the LAYOUT - ).WithVirtualFilePath( - "/Demos/WelcomeEmail/Templates", - isInlineLocalized: false - ) -); -```` - -## Global Context - -ABP passes the `model` that can be used to access to the model inside the template. You can pass more global variables if you need. - -An example template content: - -```` -A global object value: {%{{{myGlobalObject}}}%} -```` - -This template assumes that that is a `myGlobalObject` object in the template rendering context. You can provide it like shown below: - -````csharp -var result = await _templateRenderer.RenderAsync( - "GlobalContextUsage", - globalContext: new Dictionary - { - {"myGlobalObject", "TEST VALUE"} - } -); -```` - -The rendering result will be: - -```` -A global object value: TEST VALUE -```` - -## Replacing the Existing Templates - -It is possible to replace a template defined by a module that used in your application. In this way, you can customize the templates based on your requirements without changing the module code. - -### Option-1: Using the Virtual File System - -The [Virtual File System](Virtual-File-System.md) allows you to override any file by placing the same file into the same path in your project. - -#### Example: Replace the Standard Email Layout Template - -ABP Framework provides an [email sending system](Emailing.md) that internally uses the text templating to render the email content. It defines a standard email layout template in the `/Volo/Abp/Emailing/Templates/Layout.tpl` path. The unique name of the template is `Abp.StandardEmailTemplates.Layout` and this string is defined as a constant on the `Volo.Abp.Emailing.Templates.StandardEmailTemplates` static class. - -Do the following steps to replace the template file with your own; - -**1)** Add a new file into the same location (`/Volo/Abp/Emailing/Templates/Layout.tpl`) in your project: - -![replace-email-layout](images/replace-email-layout.png) - -**2)** Prepare your email layout template: - -````html - - - - - - -

This my header

- - {%{{{content}}}%} - -
- This is my footer... -
- - -```` - -This example simply adds a header and footer to the template and renders the content between them (see the *Layout Templates* section above to understand it). - -**3)** Configure the embedded resources in the `.csproj` file - -* Add [Microsoft.Extensions.FileProviders.Embedded](https://www.nuget.org/packages/Microsoft.Extensions.FileProviders.Embedded) NuGet package to the project. -* Add `true` into the `...` section of your `.csproj` file. -* Add the following code into your `.csproj` file: - -````xml - - - - -```` - -This makes the template files "embedded resource". - -**4)** Configure the virtual file system - -Configure the `AbpVirtualFileSystemOptions` in the `ConfigureServices` method of your [module](Module-Development-Basics.md) to add the embedded files into the virtual file system: - -```csharp -Configure(options => -{ - options.FileSets.AddEmbedded(); -}); -``` - -`BookStoreDomainModule` should be your module name, in this example code. - -> Be sure that your module (directly or indirectly) [depends on](Module-Development-Basics.md) the `AbpEmailingModule`. Because the VFS can override files based on the dependency order. - -Now, your template will be used when you want to render the email layout template. - -### Option-2: Using the Template Definition Provider - -You can create a template definition provider class that gets the email layout template and changes the virtual file path for the template. - -**Example: Use the `/MyTemplates/EmailLayout.tpl` file instead of the standard template** - -```csharp -using Volo.Abp.DependencyInjection; -using Volo.Abp.Emailing.Templates; -using Volo.Abp.TextTemplating; - -namespace MyProject -{ - public class MyTemplateDefinitionProvider - : TemplateDefinitionProvider, ITransientDependency - { - public override void Define(ITemplateDefinitionContext context) - { - var emailLayoutTemplate = context.GetOrNull(StandardEmailTemplates.Layout); - - emailLayoutTemplate - .WithVirtualFilePath( - "/MyTemplates/EmailLayout.tpl", - isInlineLocalized: true - ); - } - } -} -``` - -You should still add the file `/MyTemplates/EmailLayout.tpl` to the virtual file system as explained before. This approach allows you to locate templates in any folder instead of the folder defined by the depended module. - -Beside the template content, you can manipulate the template definition properties, like `DisplayName`, `Layout` or `LocalizationSource`. - -## Advanced Features - -This section covers some internals and more advanced usages of the text templating system. - -### Template Content Provider - -`ITemplateRenderer` is used to render the template, which is what you want for most of the cases. However, you can use the `ITemplateContentProvider` to get the raw (not rendered) template contents. - -> `ITemplateContentProvider` is internally used by the `ITemplateRenderer` to get the raw template contents. - -Example: - -````csharp -public class TemplateContentDemo : ITransientDependency -{ - private readonly ITemplateContentProvider _templateContentProvider; - - public TemplateContentDemo(ITemplateContentProvider templateContentProvider) - { - _templateContentProvider = templateContentProvider; - } - - public async Task RunAsync() - { - var result = await _templateContentProvider - .GetContentOrNullAsync("Hello"); - - Console.WriteLine(result); - } -} -```` - -The result will be the raw template content: - -```` -Hello {%{{{model.name}}}%} :) -```` - -* `GetContentOrNullAsync` returns `null` if no content defined for the requested template. -* It can get a `cultureName` parameter that is used if template has different files for different cultures (see Multiple Contents Localization section above). - -### Template Content Contributor - -`ITemplateContentProvider` service uses `ITemplateContentContributor` implementations to find template contents. There is a single pre-implemented content contributor, `VirtualFileTemplateContentContributor`, which gets template contents from the virtual file system as described above. - -You can implement the `ITemplateContentContributor` to read raw template contents from another source. - -Example: - -````csharp -public class MyTemplateContentProvider - : ITemplateContentContributor, ITransientDependency -{ - public async Task GetOrNullAsync(TemplateContentContributorContext context) - { - var templateName = context.TemplateDefinition.Name; - - //TODO: Try to find content from another source - return null; - } -} - -```` - -Return `null` if your source can not find the content, so `ITemplateContentProvider` fallbacks to the next contributor. - -### Template Definition Manager - -`ITemplateDefinitionManager` service can be used to get the template definitions (created by the template definition providers). +Get [the source code of the sample application](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo) developed and referred through this document. ## See Also * [The source code of the sample application](https://github.com/abpframework/abp-samples/tree/master/TextTemplateDemo) developed and referred through this document. * [Localization system](Localization.md). -* [Virtual File System](Virtual-File-System.md). +* [Virtual File System](Virtual-File-System.md). \ No newline at end of file diff --git a/docs/en/UI/AspNetCore/Navigation-Menu.md b/docs/en/UI/AspNetCore/Navigation-Menu.md index 8480590f50..97e3d1a47d 100644 --- a/docs/en/UI/AspNetCore/Navigation-Menu.md +++ b/docs/en/UI/AspNetCore/Navigation-Menu.md @@ -104,7 +104,6 @@ There are more options of a menu item (the constructor of the `ApplicationMenuIt * `target` (`string`): Target of the menu item. Can be `null` (default), "\_*blank*", "\_*self*", "\_*parent*", "\_*top*" or a frame name for web applications. * `elementId` (`string`): Can be used to render the element with a specific HTML `id` attribute. * `cssClass` (`string`): Additional string classes for the menu item. -* `RequiredPermissionName` (`string`): The required permission name, this menu item will be removed if this permission is not granted. ### Authorization @@ -121,21 +120,21 @@ if (await context.IsGrantedAsync("MyPermissionName")) } ```` -For the authorization, you can use `RequiredPermissionName` as a shortcut. It is also more performant, ABP optimizes the permission check for all the items. +For the authorization, you can use `RequirePermissions` extension method as a shortcut. It is also more performant, ABP optimizes the permission check for all the items. ````csharp context.Menu.AddItem( new ApplicationMenuItem("MyProject.Crm", l["Menu:CRM"]) .AddItem(new ApplicationMenuItem( - name: "MyProject.Crm.Customers", - displayName: l["Menu:Customers"], - url: "/crm/customers", - requiredPermissionName: "MyProject.Crm.Customers") + name: "MyProject.Crm.Customers", + displayName: l["Menu:Customers"], + url: "/crm/customers") + .RequirePermissions("MyProject.Crm.Customers") ).AddItem(new ApplicationMenuItem( - name: "MyProject.Crm.Orders", - displayName: l["Menu:Orders"], - url: "/crm/orders", - requiredPermissionName: "MyProject.Crm.Orders") + name: "MyProject.Crm.Orders", + displayName: l["Menu:Orders"], + url: "/crm/orders") + .RequirePermissions("MyProject.Crm.Orders") ) ); ```` diff --git a/docs/en/UI/AspNetCore/Toolbars.md b/docs/en/UI/AspNetCore/Toolbars.md index 66ec7519b8..d82150b47e 100644 --- a/docs/en/UI/AspNetCore/Toolbars.md +++ b/docs/en/UI/AspNetCore/Toolbars.md @@ -61,10 +61,10 @@ if (await context.IsGrantedAsync("MyPermissionName")) } ```` -You can use `RequiredPermissionName` as a shortcut. It is also more performant, ABP optimizes the permission check for all the items. +You can use `RequirePermissions` extension method as a shortcut. It is also more performant, ABP optimizes the permission check for all the items. ````csharp -context.Toolbar.Items.Insert(0, new ToolbarItem(typeof(NotificationViewComponent), requiredPermissionName: "MyPermissionName")); +context.Toolbar.Items.Insert(0, new ToolbarItem(typeof(NotificationViewComponent)).RequirePermissions("MyPermissionName")); ```` This class adds the `NotificationViewComponent` as the first item in the `Main` toolbar. diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 9a9db91d68..8abfddd251 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -9,7 +9,21 @@ "items": [ { "text": "Web Application", - "path": "Getting-Started.md" + "path": "Getting-Started.md", + "items": [ + { + "text": "1: Setup Your Development Environment", + "path": "Getting-Started-Setup-Environment.md" + }, + { + "text": "2: Creating a New Solution", + "path": "Getting-Started-Create-Solution.md" + }, + { + "text": "3: Running the Solution", + "path": "Getting-Started-Running-Solution.md" + } + ] }, { "text": "Console Application", @@ -85,7 +99,17 @@ }, { "text": "CLI", - "path": "CLI.md" + "path": "CLI.md", + "items": [ + { + "text": "Build Command", + "path": "CLI-BuildCommand.md" + }, + { + "text": "Create Solution Sample Commands", + "path": "CLI-New-Command-Samples.md" + } + ] }, { "text": "Startup Templates", @@ -350,7 +374,17 @@ }, { "text": "Text Templating", - "path": "Text-Templating.md" + "path": "Text-Templating.md", + "items": [ + { + "text": "Razor Integration", + "path": "Text-Templating-Razor.md" + }, + { + "text": "Scriban Integration", + "path": "Text-Templating-Scriban.md" + } + ] }, { "text": "Timing", @@ -363,6 +397,10 @@ { "text": "Cancellation Token Provider", "path": "Cancellation-Token-Provider.md" + }, + { + "text": "Simple State Checker", + "path": "SimpleStateChecker.md" } ] }, @@ -384,9 +422,70 @@ "text": "Customizing/Extending Modules", "path": "Customizing-Application-Modules-Guide.md" }, + { + "text": "Customizing/Extending Entities", + "path": "Customizing-Application-Modules-Extending-Entities.md" + }, + { + "text": "Customizing/Overriding Services", + "path": "Customizing-Application-Modules-Overriding-Services.md" + }, + { + "text": "Module Entity Extensions", + "path": "Module-Entity-Extensions.md" + }, { "text": "Best Practices", - "path": "Best-Practices/Index.md" + "path": "Best-Practices/Index.md", + "items": [ + { + "text": "Module Architecture", + "path": "Best-Practices/Module-Architecture.md" + }, + { + "text": "Domain Layer", + "items": [ + { + "text": "Entities", + "path": "Best-Practices/Entities.md" + }, + { + "text": "Repositories", + "path": "Best-Practices/Repositories.md" + }, + { + "text": "Domain Services", + "path": "Best-Practices/Domain-Services.md" + } + ] + }, + { + "text": "Application Layer", + "items": [ + { + "text": "Application Services", + "path": "Best-Practices/Application-Services.md" + }, + { + "text": "Data Transfer Objects", + "path": "Best-Practices/Data-Transfer-Objects.md" + } + ] + }, + { + "text": "Data Access", + "items": [ + { + "text": "Entity Framework Core Integration", + "path": "Best-Practices/Entity-Framework-Core-Integration.md" + }, + { + "text": "MongoDB Integration", + "path": "Best-Practices/MongoDB-Integration.md" + } + ] + } + ] } ] }, @@ -404,6 +503,10 @@ "text": "Entities & Aggregate Roots", "path": "Entities.md" }, + { + "text": "Multi Lingual Entities", + "path": "Multi-Lingual-Entities.md" + }, { "text": "Value Objects", "path": "Value-Objects.md" @@ -631,6 +734,18 @@ { "text": "Customize/Extend the UI", "path": "UI/AspNetCore/Customization-User-Interface.md" + }, + { + "text": "Entity Action Extensions", + "path": "UI/AspNetCore/Entity-Action-Extensions.md" + }, + { + "text": "Data Table Column Extensions", + "path": "UI/AspNetCore/Data-Table-Column-Extensions.md" + }, + { + "text": "Page Toolbar Extensions", + "path": "UI/AspNetCore/Page-Toolbar-Extensions.md" } ] }, @@ -817,6 +932,10 @@ { "text": "Multi Tenancy", "path": "UI/Angular/Multi-Tenancy.md" + }, + { + "text": "Account Module", + "path": "UI/Angular/Account-Module" } ] }, @@ -870,12 +989,36 @@ { "text": "Ellipsis", "path": "UI/Angular/Ellipsis-Directive.md" + }, + { + "text": "Context Strategy", + "path": "UI/Angular/Context-Strategy.md" + }, + { + "text": "Cross Origin Strategy", + "path": "UI/Angular/Cross-Origin-Strategy.md" + }, + { + "text": "Dom Strategy", + "path": "UI/Angular/Dom-Strategy.md" + }, + { + "text": "Container Strategy", + "path": "UI/Angular/Container-Strategy.md" + }, + { + "text": "Content Security Strategy", + "path": "UI/Angular/Content-Security-Strategy.md" } ] }, { "text": "Customization", "items": [ + { + "text": "Customization Guide", + "path": "UI/Angular/Customization-User-Interface.md" + }, { "text": "Modifying the Menu", "path": "UI/Angular/Modifying-the-Menu.md" @@ -934,6 +1077,10 @@ { "text": "Common", "items": [ + { + "text": "Overriding the User Interface", + "path": "Customizing-Application-Modules-Overriding-User-Interface.md" + }, { "text": "Utilities", "items": [ @@ -976,7 +1123,17 @@ }, { "text": "To Oracle", - "path": "Entity-Framework-Core-Oracle.md" + "path": "Entity-Framework-Core-Oracle.md", + "items": [ + { + "text": "Oracle", + "path": "Entity-Framework-Core-Oracle-Official.md" + }, + { + "text": "Oracle Devart", + "path": "Entity-Framework-Core-Oracle-Devart.md" + } + ] }, { "text": "To SQLite", @@ -1104,7 +1261,56 @@ }, { "text": "Migration Guides", - "path": "Migration-Guides/Index.md" + "path": "Migration-Guides/Index.md", + "items": [ + { + "text": "MVC / Razor Pages", + "items": [ + { + "text": "3.3 to 4.0", + "path": "Migration-Guides/Abp-4_0-MVC-Razor-Pages.md" + } + ] + }, + { + "text": "Blazor", + "items": [ + { + "text": "3.2 to 3.3", + "path": "Migration-Guides/BlazorUI-3_3.md" + }, + { + "text": "3.3 to 4.0", + "path": "Migration-Guides/Abp-4_0-Blazor.md" + } + ] + }, + { + "text": "Angular", + "items": [ + { + "text": "3.3 to 4.0", + "path": "Migration-Guides/Abp-4_0-Angular.md" + } + ] + }, + { + "text": "3.3 to 4.0", + "path": "Migration-Guides/Abp-4_0.md" + }, + { + "text": "4.2", + "path": "Migration-Guides/Abp-4_2.md" + }, + { + "text": "4.x to 4.3", + "path": "Migration-Guides/Abp-4_3.md" + }, + { + "text": "Upgrading the Startup Template", + "path": "Migration-Guides/Upgrading-Startup-Template.md" + } + ] } ] }, diff --git a/docs/en/images/hello-template-razor.png b/docs/en/images/hello-template-razor.png new file mode 100644 index 0000000000..1e0e39fcec Binary files /dev/null and b/docs/en/images/hello-template-razor.png differ diff --git a/docs/en/images/multiple-file-template-razor.png b/docs/en/images/multiple-file-template-razor.png new file mode 100644 index 0000000000..85f87e84f4 Binary files /dev/null and b/docs/en/images/multiple-file-template-razor.png differ diff --git a/docs/en/images/replace-email-layout-razor.png b/docs/en/images/replace-email-layout-razor.png new file mode 100644 index 0000000000..84ff6c1080 Binary files /dev/null and b/docs/en/images/replace-email-layout-razor.png differ diff --git a/docs/zh-Hans/Blob-Storing-Minio.md b/docs/zh-Hans/Blob-Storing-Minio.md index fb98281f02..bc0268b5cf 100644 --- a/docs/zh-Hans/Blob-Storing-Minio.md +++ b/docs/zh-Hans/Blob-Storing-Minio.md @@ -42,7 +42,7 @@ Configure(options => * **EndPoint** (string): 你的Minio对象存储服务的URL, 查看文档:https://docs.min.io/docs/dotnet-client-quickstart-guide.html * **AccessKey** (string): Access key是唯一标识你的账户的用户ID, -* **SecretKey** (string): Access key是唯一标识你的账户的用户ID +* **SecretKey** (string): Secret Key是你的账户的密码 * **BucketName** (string):你可以指定bucket名称,如果没有指定,将使用 `BlobContainerName` 属性定义的BLOB容器的名称(查阅[BLOB storing document](Blob-Storing.md)),MinIO完全兼容S3标准,所以有一些 **bucket命名规则**,必须符合[规则](https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html): * Bucket名称必须介于 3 到 63 个字符之间. * Bucket名称只能由小写字母、数字、句点 (.) 和连字符 (-) 组成. diff --git a/docs/zh-Hans/Entity-Framework-Core.md b/docs/zh-Hans/Entity-Framework-Core.md index b5252b86c0..4139407f04 100644 --- a/docs/zh-Hans/Entity-Framework-Core.md +++ b/docs/zh-Hans/Entity-Framework-Core.md @@ -433,7 +433,19 @@ public class BookRepository : EfCoreRepository, ### 替换其他仓储 -正确定义并使用DbContext接口后,任何其他实现都可以使用以下ReplaceDbContext options 替换它: +正确定义并使用DbContext接口后,任何其他实现都可以使用以下方法替换它: + +**ReplaceDbContextAttribute** + +```csharp +[ReplaceDbContext(typeof(IBookStoreDbContext))] +public class OtherDbContext : AbpDbContext, IBookStoreDbContext +{ + //... +} +``` + +**ReplaceDbContext option** ````csharp context.Services.AddAbpDbContext(options => diff --git a/docs/zh-Hans/MongoDB.md b/docs/zh-Hans/MongoDB.md index af63642a41..87c99d3207 100644 --- a/docs/zh-Hans/MongoDB.md +++ b/docs/zh-Hans/MongoDB.md @@ -329,7 +329,19 @@ public class BookRepository ##### 替换其他的DbContexts -一旦你正确定义并为MongoDbContext使用了接口,其他的实现就可以使用`ReplaceDbContext`来替换: +一旦你正确定义并为MongoDbContext使用了接口,任何其他实现都可以使用以下方法替换它: + +**ReplaceDbContextAttribute** + +```csharp +[ReplaceDbContext(typeof(IBookStoreMongoDbContext))] +public class OtherMongoDbContext : AbpMongoDbContext, IBookStoreMongoDbContext +{ + //... +} +``` + +**ReplaceDbContext option** ```csharp context.Services.AddMongoDbContext(options => diff --git a/docs/zh-Hans/Value-Objects.md b/docs/zh-Hans/Value-Objects.md index 6735074fd4..c5dd929ff2 100644 --- a/docs/zh-Hans/Value-Objects.md +++ b/docs/zh-Hans/Value-Objects.md @@ -1,3 +1,75 @@ -## Value Objects +## 值对象 - TODO \ No newline at end of file +> 一个对象,表示领域的描述方面,没有概念上的身份被称为 值对象. +> +> (Eric Evans) + +属性相同但`Id`不同的两个[实体](https://docs.abp.io/zh-Hans/abp/latest/Entities) 被视为不同的实体.但是,值对象没有`Id` + +## 值对象的类 + +值对象是一个抽象类,可以继承它来创建值对象类 + +**示例: An Address class** + +```csharp +public class Address : ValueObject +{ + public Guid CityId { get; private set; } + + public string Street { get; private set; } + + public int Number { get; private set; } + + private Address() + { + + } + + public Address( + Guid cityId, + string street, + int number) + { + CityId = cityId; + Street = street; + Number = number; + } + + protected override IEnumerable GetAtomicValues() + { + yield return Street; + yield return CityId; + yield return Number; + } +} +``` + +- 值对象类必须实现 `GetAtomicValues()`方法来返回原始值 + +### ValueEquals + +`ValueObject.ValueEquals(...)` 用于检测两个值是否相等 + +**示例: Check if two addresses are equals** + +```csharp +Address address1 = ... +Address address2 = ... + +if (address1.ValueEquals(address2)) //Check equality +{ + ... +} +``` + +## 最佳实践 + +以下是使用值对象时的一些最佳实践: + +- 如果没有充分的理由将值对象设计为可变的,则将其设计为**不可变**(如上面的地址). +- 构成一个值对象的属性应该形成一个概念整体.例如:CityId,Street和Number不应是个人实体的单独属性.这也使Person实体更简单. + +## 另请参阅 + +- [实体](Entities.md) diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index bdc2745705..b71288ab93 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -385,6 +385,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Authorization.Abstractions", "src\Volo.Abp.Authorization.Abstractions\Volo.Abp.Authorization.Abstractions.csproj", "{87B0C2A8-FE95-4779-8B9C-2181AA52B3FA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Core", "src\Volo.Abp.TextTemplating.Core\Volo.Abp.TextTemplating.Core.csproj", "{184E859A-282D-44D7-B8E9-FEA874644013}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Scriban", "src\Volo.Abp.TextTemplating.Scriban\Volo.Abp.TextTemplating.Scriban.csproj", "{228723E6-FA6D-406B-B8F8-C9BCC547AF8E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Razor", "src\Volo.Abp.TextTemplating.Razor\Volo.Abp.TextTemplating.Razor.csproj", "{42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Razor.Tests", "test\Volo.Abp.TextTemplating.Razor.Tests\Volo.Abp.TextTemplating.Razor.Tests.csproj", "{C996F458-98FB-483D-9306-4701290E2FC1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Scriban.Tests", "test\Volo.Abp.TextTemplating.Scriban.Tests\Volo.Abp.TextTemplating.Scriban.Tests.csproj", "{75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.MongoDB.Tests.SecondContext", "test\Volo.Abp.MongoDB.Tests.SecondContext\Volo.Abp.MongoDB.Tests.SecondContext.csproj", "{90B1866A-EF99-40B9-970E-B898E5AA523F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1147,6 +1159,30 @@ Global {87B0C2A8-FE95-4779-8B9C-2181AA52B3FA}.Debug|Any CPU.Build.0 = Debug|Any CPU {87B0C2A8-FE95-4779-8B9C-2181AA52B3FA}.Release|Any CPU.ActiveCfg = Release|Any CPU {87B0C2A8-FE95-4779-8B9C-2181AA52B3FA}.Release|Any CPU.Build.0 = Release|Any CPU + {184E859A-282D-44D7-B8E9-FEA874644013}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {184E859A-282D-44D7-B8E9-FEA874644013}.Debug|Any CPU.Build.0 = Debug|Any CPU + {184E859A-282D-44D7-B8E9-FEA874644013}.Release|Any CPU.ActiveCfg = Release|Any CPU + {184E859A-282D-44D7-B8E9-FEA874644013}.Release|Any CPU.Build.0 = Release|Any CPU + {228723E6-FA6D-406B-B8F8-C9BCC547AF8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {228723E6-FA6D-406B-B8F8-C9BCC547AF8E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {228723E6-FA6D-406B-B8F8-C9BCC547AF8E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {228723E6-FA6D-406B-B8F8-C9BCC547AF8E}.Release|Any CPU.Build.0 = Release|Any CPU + {42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19}.Release|Any CPU.Build.0 = Release|Any CPU + {C996F458-98FB-483D-9306-4701290E2FC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C996F458-98FB-483D-9306-4701290E2FC1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C996F458-98FB-483D-9306-4701290E2FC1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C996F458-98FB-483D-9306-4701290E2FC1}.Release|Any CPU.Build.0 = Release|Any CPU + {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}.Release|Any CPU.Build.0 = Release|Any CPU + {90B1866A-EF99-40B9-970E-B898E5AA523F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90B1866A-EF99-40B9-970E-B898E5AA523F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1341,6 +1377,12 @@ Global {B4B6B7DE-9798-4007-B1DF-7EE7929E392A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {E9CE58DB-0789-4D18-8B63-474F7D7B14B4} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {87B0C2A8-FE95-4779-8B9C-2181AA52B3FA} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {184E859A-282D-44D7-B8E9-FEA874644013} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {228723E6-FA6D-406B-B8F8-C9BCC547AF8E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {C996F458-98FB-483D-9306-4701290E2FC1} = {447C8A77-E5F0-4538-8687-7383196D04EA} + {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C} = {447C8A77-E5F0-4538-8687-7383196D04EA} + {90B1866A-EF99-40B9-970E-B898E5AA523F} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs index e98280d19d..160e66f49f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.OAuth.Claims; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Volo.Abp.AspNetCore.MultiTenancy; namespace Microsoft.Extensions.DependencyInjection @@ -35,6 +36,17 @@ namespace Microsoft.Extensions.DependencyInjection SetAbpTenantId(receivedContext); return authorizationCodeReceived.Invoke(receivedContext); }; + + options.Events.OnRemoteFailure = remoteFailureContext => + { + if (remoteFailureContext.Failure is OpenIdConnectProtocolException && + remoteFailureContext.Failure.Message.Contains("access_denied")) + { + remoteFailureContext.HandleResponse(); + remoteFailureContext.Response.Redirect($"{remoteFailureContext.Request.PathBase}/"); + } + return Task.CompletedTask; + }; }); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/AppWithoutAuth.razor b/framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/AppWithoutAuth.razor new file mode 100644 index 0000000000..e9bf522595 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/AppWithoutAuth.razor @@ -0,0 +1,14 @@ +@using Microsoft.Extensions.Options +@using Volo.Abp.AspNetCore.Components.Web.Theming.Routing +@inject IOptions RouterOptions + + + + + + +

Sorry, there's nothing at this address.

+
+
+
\ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs index 281b2f7ded..787bf5cb6e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpComponentsClaimsCache.cs @@ -1,5 +1,6 @@ using System.Security.Claims; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; @@ -14,21 +15,29 @@ namespace Volo.Abp.AspNetCore.Components.Web.Security { public ClaimsPrincipal Principal { get; private set; } + [CanBeNull] private readonly AuthenticationStateProvider _authenticationStateProvider; - public AbpComponentsClaimsCache(IClientScopeServiceProviderAccessor clientScopeServiceProviderAccessor) + public AbpComponentsClaimsCache( + IClientScopeServiceProviderAccessor serviceProviderAccessor) { - _authenticationStateProvider = clientScopeServiceProviderAccessor.ServiceProvider.GetRequiredService(); - _authenticationStateProvider.AuthenticationStateChanged += async (task) => + _authenticationStateProvider = serviceProviderAccessor.ServiceProvider.GetService(); + if (_authenticationStateProvider != null) { - Principal = (await task).User; - }; + _authenticationStateProvider.AuthenticationStateChanged += async (task) => + { + Principal = (await task).User; + }; + } } public virtual async Task InitializeAsync() { - var authenticationState = await _authenticationStateProvider.GetAuthenticationStateAsync(); - Principal = authenticationState.User; + if (_authenticationStateProvider != null) + { + var authenticationState = await _authenticationStateProvider.GetAuthenticationStateAsync(); + Principal = authenticationState.User; + } } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/BasicThemeToolbarContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/BasicThemeToolbarContributor.cs index ab2a73a8dd..b853670d39 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/BasicThemeToolbarContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/BasicThemeToolbarContributor.cs @@ -1,7 +1,10 @@ using System.Threading.Tasks; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic; using Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; using Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic; +using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme { @@ -12,7 +15,15 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme if (context.Toolbar.Name == StandardToolbars.Main) { context.Toolbar.Items.Add(new ToolbarItem(typeof(LanguageSwitch))); - context.Toolbar.Items.Add(new ToolbarItem(typeof(LoginDisplay))); + + //TODO: Can we find a different way to understand if authentication was configured or not? + var authenticationStateProvider = context.ServiceProvider + .GetService(); + + if (authenticationStateProvider != null) + { + context.Toolbar.Items.Add(new ToolbarItem(typeof(LoginDisplay))); + } } return Task.CompletedTask; diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor index eebfb501a5..1b084a60ce 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor @@ -1,13 +1,12 @@ -@using Microsoft.AspNetCore.Components.WebAssembly.Authentication -@using Microsoft.Extensions.Localization +@using Microsoft.Extensions.Localization @using Volo.Abp.Users @using Volo.Abp.MultiTenancy @using global::Localization.Resources.AbpUi +@inherits AbpComponentBase @inject ICurrentUser CurrentUser @inject ICurrentTenant CurrentTenant @inject IJSRuntime JsRuntime @inject NavigationManager Navigation -@inject SignOutSessionStateManager SignOutManager @inject IStringLocalizer UiLocalizer @@ -38,24 +37,4 @@ @UiLocalizer["Login"] - -@code{ - - private async Task NavigateToAsync(string uri, string target = null) - { - if (target == "_blank") - { - await JsRuntime.InvokeVoidAsync("open", uri, target); - } - else - { - Navigation.NavigateTo(uri); - } - } - - private async Task BeginSignOut() - { - await SignOutManager.SetSignOutState(); - await NavigateToAsync("authentication/logout"); - } -} + \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs index addef3dc80..0ec9caa23c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs @@ -1,8 +1,11 @@ using System; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Routing; +using Microsoft.AspNetCore.Components.WebAssembly.Authentication; +using Microsoft.JSInterop; using Volo.Abp.UI.Navigation; namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic @@ -11,23 +14,32 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic { [Inject] protected IMenuManager MenuManager { get; set; } - - [Inject] - protected AuthenticationStateProvider AuthenticationStateProvider { get; set; } - protected ApplicationMenu Menu { get; set; } + [CanBeNull] + protected AuthenticationStateProvider AuthenticationStateProvider; + + [CanBeNull] + protected SignOutSessionStateManager SignOutManager; + protected ApplicationMenu Menu { get; set; } + protected override async Task OnInitializedAsync() { Menu = await MenuManager.GetAsync(StandardMenus.User); Navigation.LocationChanged += OnLocationChanged; - AuthenticationStateProvider.AuthenticationStateChanged += async (task) => + LazyGetService(ref AuthenticationStateProvider); + LazyGetService(ref SignOutManager); + + if (AuthenticationStateProvider != null) { - Menu = await MenuManager.GetAsync(StandardMenus.User); - await InvokeAsync(StateHasChanged); - }; + AuthenticationStateProvider.AuthenticationStateChanged += async (task) => + { + Menu = await MenuManager.GetAsync(StandardMenus.User); + await InvokeAsync(StateHasChanged); + }; + } } protected virtual void OnLocationChanged(object sender, LocationChangedEventArgs e) @@ -39,5 +51,26 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic { Navigation.LocationChanged -= OnLocationChanged; } + + private async Task NavigateToAsync(string uri, string target = null) + { + if (target == "_blank") + { + await JsRuntime.InvokeVoidAsync("open", uri, target); + } + else + { + Navigation.NavigateTo(uri); + } + } + + private async Task BeginSignOut() + { + if (SignOutManager != null) + { + await SignOutManager.SetSignOutState(); + await NavigateToAsync("authentication/logout"); + } + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs index bc4db53002..163b2217fa 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs @@ -108,6 +108,18 @@ namespace Volo.Abp.AspNetCore.Components return reference; } + + protected TService LazyGetService(ref TService reference) => LazyGetService(typeof(TService), ref reference); + + protected TRef LazyGetService(Type serviceType, ref TRef reference) + { + if (reference == null) + { + reference = (TRef)ScopedServices.GetService(serviceType); + } + + return reference; + } protected TService LazyGetNonScopedRequiredService(ref TService reference) => LazyGetNonScopedRequiredService(typeof(TService), ref reference); @@ -120,6 +132,18 @@ namespace Volo.Abp.AspNetCore.Components return reference; } + + protected TService LazyGetNonScopedService(ref TService reference) => LazyGetNonScopedService(typeof(TService), ref reference); + + protected TRef LazyGetNonScopedService(Type serviceType, ref TRef reference) + { + if (reference == null) + { + reference = (TRef)NonScopedServices.GetService(serviceType); + } + + return reference; + } [Inject] protected IServiceProvider NonScopedServices { get; set; } diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyOptions.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyOptions.cs index 63b83885f9..b2ecf708c5 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyOptions.cs @@ -1,4 +1,9 @@ -using Volo.Abp.MultiTenancy; +using System; +using System.Globalization; +using System.Net; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Volo.Abp.MultiTenancy; namespace Volo.Abp.AspNetCore.MultiTenancy { @@ -9,9 +14,26 @@ namespace Volo.Abp.AspNetCore.MultiTenancy /// public string TenantKey { get; set; } + public Func MultiTenancyMiddlewareErrorPageBuilder { get; set; } + public AbpAspNetCoreMultiTenancyOptions() { TenantKey = TenantResolverConsts.DefaultTenantKey; + MultiTenancyMiddlewareErrorPageBuilder = async (context, exception)=> + { + context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;; + context.Response.ContentType = "text/html"; + + var message = exception.Message; + var details = exception is BusinessException businessException ? businessException.Details : string.Empty; + + await context.Response.WriteAsync($"\r\n"); + await context.Response.WriteAsync($"

{message}

{details}
\r\n"); + await context.Response.WriteAsync("\r\n"); + + // Note the 500 spaces are to work around an IE 'feature' + await context.Response.WriteAsync(new string(' ', 500)); + }; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs index eaf5c753fd..361826672b 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs @@ -1,10 +1,14 @@ using System; using System.Globalization; +using System.IO; +using System.Net; using System.Threading.Tasks; +using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.RequestLocalization; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.Localization; using Volo.Abp.MultiTenancy; @@ -16,18 +20,31 @@ namespace Volo.Abp.AspNetCore.MultiTenancy { private readonly ITenantConfigurationProvider _tenantConfigurationProvider; private readonly ICurrentTenant _currentTenant; + private readonly AbpAspNetCoreMultiTenancyOptions _options; public MultiTenancyMiddleware( ITenantConfigurationProvider tenantConfigurationProvider, - ICurrentTenant currentTenant) + ICurrentTenant currentTenant, + IOptions options) { _tenantConfigurationProvider = tenantConfigurationProvider; _currentTenant = currentTenant; + _options = options.Value; } public async Task InvokeAsync(HttpContext context, RequestDelegate next) { - var tenant = await _tenantConfigurationProvider.GetAsync(saveResolveResult: true); + TenantConfiguration tenant; + try + { + tenant = await _tenantConfigurationProvider.GetAsync(saveResolveResult: true); + } + catch (Exception e) + { + await _options.MultiTenancyMiddlewareErrorPageBuilder(context, e); + return; + } + if (tenant?.Id != _currentTenant.Id) { using (_currentTenant.Change(tenant?.Id, tenant?.Name)) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs index d85622f0cf..6f834b18ea 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs @@ -10,5 +10,7 @@ namespace Volo.Abp.AspNetCore.Mvc.MultiTenancy public Guid? TenantId { get; set; } public string Name { get; set; } + + public bool IsActive { get; set; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs index 6afb918704..1a94e3f536 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs @@ -13,9 +13,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse { SetRandomIdIfNotProvided(); - var innerContent = (await output.GetChildContentAsync()).GetContent(); + var childContent = await output.GetChildContentAsync(); - var html = GetAccordionHeaderItem(context, output) + GetAccordionContentItem(context, output, innerContent); + var html = GetAccordionHeaderItem(context, output) + GetAccordionContentItem(context, output, childContent); var tabHeaderItems = context.GetValue>(AccordionItems); tabHeaderItems.Add(html); @@ -46,7 +46,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse return header.ToHtmlString(); } - protected virtual string GetAccordionContentItem(TagHelperContext context, TagHelperOutput output, string content) + protected virtual string GetAccordionContentItem(TagHelperContext context, TagHelperOutput output, TagHelperContent content) { var show = (TagHelper.Active ?? false) ? " show" : ""; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelperService.cs index 3c429b32ef..843efae0f4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpCollapseBodyTagHelperService.cs @@ -22,9 +22,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse output.Attributes.AddClass("multi-collapse"); } - var innerContent = (await output.GetChildContentAsync()).GetContent(); + var childContent = await output.GetChildContentAsync(); - output.Content.SetHtmlContent(innerContent); + output.Content.SetHtmlContent(childContent); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs index c6a0307d2d..6b18f8ee90 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Dropdown/AbpDropdownButtonTagHelperService.cs @@ -70,7 +70,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown var buttonTag = await abpButtonTagHelper.ProcessAndGetOutputAsync(attributes, context, "button", TagMode.StartTagAndEndTag); - buttonTag.PreContent.SetHtmlContent(content.GetContent()); + buttonTag.PreContent.SetHtmlContent(content); if ((TagHelper.NavLink ?? false) || (TagHelper.Link ?? false)) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs index 7d2f0804b7..410a3d1454 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs @@ -42,7 +42,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form NormalizeTagMode(context, output); - var childContent = (await output.GetChildContentAsync()).GetContent(); + var childContent = await output.GetChildContentAsync(); await ConvertToMvcForm(context, output); @@ -78,8 +78,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form await formTagOutput.GetChildContentAsync(); - output.PostContent.SetHtmlContent(output.PostContent.GetContent() + formTagOutput.PostContent.GetContent()); - output.PreContent.SetHtmlContent(output.PreContent.GetContent() + formTagOutput.PreContent.GetContent()); + output.PostContent.AppendHtml(formTagOutput.PostContent); + output.PreContent.AppendHtml(formTagOutput.PreContent); } protected virtual void NormalizeTagMode(TagHelperContext context, TagHelperOutput output) @@ -93,7 +93,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form output.Attributes.AddIfNotContains("method", "post"); } - protected virtual void SetContent(TagHelperContext context, TagHelperOutput output, List items, string childContent) + protected virtual void SetContent(TagHelperContext context, TagHelperOutput output, List items, TagHelperContent childContent) { var contentBuilder = new StringBuilder(""); @@ -102,16 +102,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form contentBuilder.AppendLine(item.HtmlContent); } - if (childContent.Contains(AbpFormContentPlaceHolder)) + var content = childContent.GetContent(); + if (content.Contains(AbpFormContentPlaceHolder)) { - childContent = childContent.Replace(AbpFormContentPlaceHolder, contentBuilder.ToString()); + content = content.Replace(AbpFormContentPlaceHolder, contentBuilder.ToString()); } else { - childContent = contentBuilder + childContent; + content = contentBuilder + content; } - output.Content.SetHtmlContent(childContent); + output.Content.SetHtmlContent(content); } protected virtual async Task SetSubmitButton(TagHelperContext context, TagHelperOutput output) @@ -123,7 +124,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form var buttonHtml = await ProcessSubmitButtonAndGetContentAsync(context, output); - output.PostContent.SetHtmlContent(output.PostContent.GetContent() + buttonHtml); + output.PostContent.AppendHtml(buttonHtml); } protected virtual List InitilizeFormGroupContentsContext(TagHelperContext context, TagHelperOutput output) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs index 965987f10d..0802360579 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs @@ -57,7 +57,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form output.Attributes.AddClass(isCheckBox ? "custom-checkbox" : "form-group"); output.Attributes.AddClass(isCheckBox ? "custom-control" : ""); output.Attributes.AddClass(isCheckBox ? "mb-2" : ""); - output.Content.SetHtmlContent(output.Content.GetContent() + innerHtml); + output.Content.AppendHtml(innerHtml); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs index 2f4440b904..20ade14b49 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs @@ -5,12 +5,15 @@ using Microsoft.AspNetCore.Razor.TagHelpers; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form { + [OutputElementHint("select")] public class AbpSelectTagHelper : AbpTagHelper { public ModelExpression AspFor { get; set; } public string Label { get; set; } + public bool SuppressLabel { get; set; } + public IEnumerable AspItems { get; set; } public AbpFormControlSize Size { get; set; } = AbpFormControlSize.Default; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs index 6050fb91d6..f651c24874 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs @@ -38,7 +38,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { - var innerHtml = await GetFormInputGroupAsHtmlAsync(context, output); + var childContent = await output.GetChildContentAsync(); + + var innerHtml = await GetFormInputGroupAsHtmlAsync(context, output, childContent); var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder(); @@ -58,9 +60,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form } } - protected virtual async Task GetFormInputGroupAsHtmlAsync(TagHelperContext context, TagHelperOutput output) + protected virtual async Task GetFormInputGroupAsHtmlAsync(TagHelperContext context, TagHelperOutput output, TagHelperContent childContent) { - var selectTag = await GetSelectTagAsync(context, output); + var selectTag = await GetSelectTagAsync(context, output, childContent); var selectAsHtml = selectTag.Render(_encoder); var label = await GetLabelAsHtmlAsync(context, output, selectTag); var validation = await GetValidationAsHtmlAsync(context, output, selectTag); @@ -74,7 +76,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form return "
" + Environment.NewLine + innerHtml + Environment.NewLine + "
"; } - protected virtual async Task GetSelectTagAsync(TagHelperContext context, TagHelperOutput output) + protected virtual async Task GetSelectTagAsync(TagHelperContext context, TagHelperOutput output, TagHelperContent childContent) { var selectTagHelper = new SelectTagHelper(_generator) { @@ -97,6 +99,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form var selectTagHelperOutput = await selectTagHelper.ProcessAndGetOutputAsync(GetInputAttributes(context, output), context, "select", TagMode.StartTagAndEndTag); + selectTagHelperOutput.Content.SetHtmlContent(childContent); selectTagHelperOutput.Attributes.AddClass("form-control"); selectTagHelperOutput.Attributes.AddClass(GetSize(context, output)); AddDisabledAttribute(selectTagHelperOutput); @@ -165,6 +168,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form protected virtual async Task GetLabelAsHtmlAsync(TagHelperContext context, TagHelperOutput output, TagHelperOutput selectTag) { + if (TagHelper.SuppressLabel) + { + return string.Empty; + } + if (!string.IsNullOrEmpty(TagHelper.Label)) { var label = new TagBuilder("label"); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs index a9a134ceba..c17c7c5f3d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs @@ -13,9 +13,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab { SetPlaceholderForNameIfNotProvided(); - var innerContent = await output.GetChildContentAsync(); + var childContent = await output.GetChildContentAsync(); var tabHeader = GetTabHeaderItem(context, output); - var tabContent = GetTabContentItem(context, output, innerContent.GetContent()); + var tabContent = GetTabContentItem(context, output, childContent); var tabHeaderItems = context.GetValue>(TabItems); @@ -83,7 +83,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab } } - protected virtual string GetTabContentItem(TagHelperContext context, TagHelperOutput output, string content) + protected virtual string GetTabContentItem(TagHelperContext context, TagHelperOutput output, TagHelperContent content) { var headerId = TagHelper.Name + "-tab"; var id = TagHelper.Name; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs index d0bea87196..60bdb523ba 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs @@ -28,10 +28,11 @@ namespace Pages.Abp.MultiTenancy { Success = true, TenantId = tenant.Id, - Name = tenant.Name + Name = tenant.Name, + IsActive = tenant.IsActive }; } - + public async Task FindTenantByIdAsync(Guid id) { var tenant = await TenantStore.FindAsync(id); @@ -45,8 +46,9 @@ namespace Pages.Abp.MultiTenancy { Success = true, TenantId = tenant.Id, - Name = tenant.Name + Name = tenant.Name, + IsActive = tenant.IsActive }; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs index bfdbb98db8..f47edab789 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/TenantSwitchModal.cshtml.cs @@ -20,7 +20,7 @@ namespace Pages.Abp.MultiTenancy protected AbpAspNetCoreMultiTenancyOptions Options { get; } public TenantSwitchModalModel( - ITenantStore tenantStore, + ITenantStore tenantStore, IOptions options) { TenantStore = tenantStore; @@ -49,6 +49,11 @@ namespace Pages.Abp.MultiTenancy { var tenant = await TenantStore.FindAsync(Input.Name); if (tenant == null) + { + throw new UserFriendlyException(L["GivenTenantIsNotExist", Input.Name]); + } + + if (!tenant.IsActive) { throw new UserFriendlyException(L["GivenTenantIsNotAvailable", Input.Name]); } @@ -71,4 +76,4 @@ namespace Pages.Abp.MultiTenancy public string Name { get; set; } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ar.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ar.json index 7e5f26edc6..fafc04a6ee 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ar.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ar.json @@ -1,6 +1,7 @@ { "culture": "ar", "texts": { + "GivenTenantIsNotExist": "المستأجر المحدد غير موجود: {0}", "GivenTenantIsNotAvailable": "الجهة المحددة غير متاحة: {0}", "Tenant": "الجهة", "Switch": "تغيير", @@ -9,4 +10,4 @@ "SwitchTenant": "تغيير الجهة", "NotSelected": "غير محدد" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json index 05457dfa16..0f63728c77 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/cs.json @@ -1,6 +1,7 @@ { "culture": "cs", "texts": { + "GivenTenantIsNotExist": "Vybraný tenant neexistuje: {0}", "GivenTenantIsNotAvailable": "Zvolený tenant není dostupný: {0}", "Tenant": "Tenant", "Switch": "změnit", diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/de-DE.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/de-DE.json index 3b1f12c29d..a0bb43999a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/de-DE.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/de-DE.json @@ -1,6 +1,7 @@ { "culture": "de-DE", "texts": { + "GivenTenantIsNotExist": "Der angegebene Client ist nicht vorhanden: {0}", "GivenTenantIsNotAvailable": "Der angegebene Mandant ist nicht verfügbar: {0}", "Tenant": "Mandant", "Switch": "wechseln", @@ -9,4 +10,4 @@ "SwitchTenant": "Mandant wechseln", "NotSelected": "Nicht ausgewählt" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/de.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/de.json index 98909d9847..029e7ed76a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/de.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/de.json @@ -1,6 +1,7 @@ { "culture": "de", "texts": { + "GivenTenantIsNotExist": "Der angegebene Client ist nicht vorhanden: {0}", "GivenTenantIsNotAvailable": "Der angegebene Mandant ist nicht verfügbar: {0}", "Tenant": "Mandant", "Switch": "wechseln", @@ -9,4 +10,4 @@ "SwitchTenant": "Mandant wechseln", "NotSelected": "Nicht ausgewählt" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en-GB.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en-GB.json index be5593fbd3..e93e7ef25e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en-GB.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en-GB.json @@ -1,6 +1,7 @@ { "culture": "en-GB", "texts": { + "GivenTenantIsNotExist": "Given tenant is not exist: {0}", "GivenTenantIsNotAvailable": "Given tenant is not available: {0}", "Tenant": "Tenant", "Switch": "switch", @@ -9,4 +10,4 @@ "SwitchTenant": "Switch tenant", "NotSelected": "Not selected" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json index d1a9f1f09e..25516ba765 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json @@ -1,6 +1,7 @@ { "culture": "en", "texts": { + "GivenTenantIsNotExist": "Given tenant is not exist: {0}", "GivenTenantIsNotAvailable": "Given tenant is not available: {0}", "Tenant": "Tenant", "Switch": "switch", @@ -9,4 +10,4 @@ "SwitchTenant": "Switch tenant", "NotSelected": "Not selected" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/es-mx.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/es-mx.json index 746f1dec0f..5cd08ab345 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/es-mx.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/es-mx.json @@ -1,6 +1,7 @@ { "culture": "es-MX", "texts": { + "GivenTenantIsNotExist": "El inquilino {0} no existe", "GivenTenantIsNotAvailable": "El inquilino {0} no está disponible", "Tenant": "Inquilino", "Switch": "cambiar", diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/es.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/es.json index d6fd84dcbe..bd2d82a2d0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/es.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/es.json @@ -1,6 +1,7 @@ { "culture": "es", "texts": { + "GivenTenantIsNotExist": "El inquilino {0} no existe", "GivenTenantIsNotAvailable": "El inquilino {0} no está disponible", "Tenant": "Inquilino", "Switch": "cambiar", @@ -9,4 +10,4 @@ "SwitchTenantHint": "Deje en blanco el campo nombre para cambiar el lado del host.", "NotSelected": "No seleccionado" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/fi.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/fi.json new file mode 100644 index 0000000000..d6fb04eb4c --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/fi.json @@ -0,0 +1,13 @@ +{ + "culture": "fi", + "texts": { + "GivenTenantIsNotExist": "Annettua vuokralaista ei ole olemassa: {0}", + "GivenTenantIsNotAvailable": "Annettua vuokralaista ei ole saatavilla: {0}", + "Tenant": "Vuokralainen", + "Switch": "vaihtaa", + "Name": "Nimi", + "SwitchTenantHint": "Jätä nimikenttä tyhjäksi, jos haluat vaihtaa isäntäpuolelle.", + "SwitchTenant": "Vaihda vuokralainen", + "NotSelected": "Ei valittu" + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/fr.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/fr.json index dbd17957fc..6fe00242b5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/fr.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/fr.json @@ -1,6 +1,7 @@ { "culture": "fr", "texts": { + "GivenTenantIsNotExist": "Adott bérlő nem létezik: {0}", "GivenTenantIsNotAvailable": "Le Tenant donné n'est pas disponible: {0}", "Tenant": "Tenant", "Switch": "Changer", @@ -9,4 +10,4 @@ "SwitchTenant": "Changer le Tenant", "NotSelected": "Non séléctionné" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/hi.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/hi.json new file mode 100644 index 0000000000..bc1ea195cd --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/hi.json @@ -0,0 +1,13 @@ +{ + "culture": "hi", + "texts": { + "GivenTenantIsNotExist": "किरायेदार मौजूद नहीं है: {0}", + "GivenTenantIsNotAvailable": "उपलब्ध किरायेदार उपलब्ध नहीं है: {0}", + "Tenant": "किरायेदार", + "Switch": "स्विच", + "Name": "नाम", + "SwitchTenantHint": "होस्ट फ़ील्ड पर जाने के लिए नाम फ़ील्ड रिक्त छोड़ें।", + "SwitchTenant": "किरायेदार स्विच करें", + "NotSelected": "नहीं चुने गए" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/hu.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/hu.json index 057e9d2968..108b3520d7 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/hu.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/hu.json @@ -1,6 +1,7 @@ { "culture": "hu", "texts": { + "GivenTenantIsNotExist": "Adott bérlő nem létezik: {0}", "GivenTenantIsNotAvailable": "A megadott előfizető nem érhető el: {0}", "Tenant": "Előfizető", "Switch": "váltás", @@ -9,4 +10,4 @@ "SwitchTenant": "Előfizető váltás", "NotSelected": "Nincs kiválasztva" } - } \ No newline at end of file + } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/it.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/it.json new file mode 100644 index 0000000000..e46b96fb20 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/it.json @@ -0,0 +1,13 @@ +{ + "culture": "it", + "texts": { + "GivenTenantIsNotExist": "Il tenant specificato non esiste: {0}", + "GivenTenantIsNotAvailable": "Il tenant specificato non è disponibile: {0}", + "Tenant": "Inquilino", + "Switch": "interruttore", + "Name": "Nome", + "SwitchTenantHint": "Lascia vuoto il campo del nome per passare al lato host.", + "SwitchTenant": "Cambia inquilino", + "NotSelected": "Non selezionato" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/nl.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/nl.json index ea15166b9e..3cbb689f03 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/nl.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/nl.json @@ -1,6 +1,7 @@ { "culture": "nl", "texts": { + "GivenTenantIsNotExist": "Opgegeven huurder bestaat niet: {0}", "GivenTenantIsNotAvailable": "Gegeven klant is niet beschikbaar: {0}", "Tenant": "Klant", "Switch": "Schakel over", @@ -9,4 +10,4 @@ "SwitchTenant": "Klant wisselen", "NotSelected": "Niet geselecteerd" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pl-PL.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pl-PL.json index 438d770a7c..79d3e9640d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pl-PL.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pl-PL.json @@ -1,6 +1,7 @@ { "culture": "pl-PL", "texts": { + "GivenTenantIsNotExist": "Podany najemca nie istnieje: {0}", "GivenTenantIsNotAvailable": "Podany tenant jest niedostępny: {0}", "Tenant": "Tenant", "Switch": "zmień", @@ -8,4 +9,4 @@ "SwitchTenantHint": "Pozostaw pole nazwy puste, aby przełączyć się na stronę hosta.", "NotSelected": "Nie wybrano" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json index 8ac517d594..95396abca1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json @@ -1,6 +1,7 @@ { "culture": "pt-BR", "texts": { + "GivenTenantIsNotExist": "O inquilino dado não existe: {0}", "GivenTenantIsNotAvailable": "Inquilino não está disponível: {0}", "Tenant": "Inquilino", "Switch": "trocar", @@ -9,4 +10,4 @@ "SwitchTenant": "Alterar Inquilino", "NotSelected": "Não selecionado" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ru.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ru.json index 04b2e5cf85..5492a7d7bb 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ru.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ru.json @@ -1,6 +1,7 @@ { "culture": "ru", "texts": { + "GivenTenantIsNotExist": "Данный арендатор не существует: {0}", "GivenTenantIsNotAvailable": "Данный арендатор недоступен: {0}", "Tenant": "Арендатор", "Switch": "переключиться", diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/sl.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/sl.json index 51938a569e..b1a07d3ee9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/sl.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/sl.json @@ -1,6 +1,7 @@ { "culture": "sl", "texts": { + "GivenTenantIsNotExist": "Dani najemnik ne obstaja: {0}", "GivenTenantIsNotAvailable": "Najemnik ni na voljo: {0}", "Tenant": "Najemnik", "Switch": "Zamenjaj", diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/tr.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/tr.json index 994579e934..b5b6c374c1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/tr.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/tr.json @@ -1,6 +1,7 @@ { "culture": "tr", "texts": { + "GivenTenantIsNotExist": "İstenilen müşteri bulunamadı: {0}", "GivenTenantIsNotAvailable": "İstenilen müşteri bulunamadı: {0}", "Tenant": "Müşteri", "Switch": "değiştir", @@ -9,4 +10,4 @@ "SwitchTenant": "Müşteri değiştir", "NotSelected": "Seçili değil" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/vi.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/vi.json index 975e1b4590..b8ad08bb82 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/vi.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/vi.json @@ -1,6 +1,7 @@ { "culture": "vi", "texts": { + "GivenTenantIsNotExist": "Người thuê đã cho không tồn tại: {0}", "GivenTenantIsNotAvailable": "Người thuê không có sẵn: {0}", "Tenant": "Người thuê", "Switch": "Chuyển đổi", diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hans.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hans.json index 31588cbebd..0e86d66293 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hans.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hans.json @@ -1,6 +1,7 @@ { "culture": "zh-Hans", "texts": { + "GivenTenantIsNotExist": "给定的租户不存在: {0}", "GivenTenantIsNotAvailable": "给定的租户不可用: {0}", "Tenant": "租户", "Switch": "切换", @@ -9,4 +10,4 @@ "SwitchTenant": "切换租户", "NotSelected": "未选中" } - } \ No newline at end of file + } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hant.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hant.json index 12eea67007..10a0da1023 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hant.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hant.json @@ -1,6 +1,7 @@ { "culture": "zh-Hant", "texts": { + "GivenTenantIsNotExist": "指定的租戶不存在: {0}", "GivenTenantIsNotAvailable": "指定的租戶不可用: {0}", "SwitchTenant": "切換租戶", "Name": "名稱", @@ -9,4 +10,4 @@ "Switch": "切換", "NotSelected": "尚未選定" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/TuiEditor/TuiEditorScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/TuiEditor/TuiEditorScriptContributor.cs index e2e826445f..a6342c6276 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/TuiEditor/TuiEditorScriptContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/TuiEditor/TuiEditorScriptContributor.cs @@ -16,7 +16,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor { public override void ConfigureBundle(BundleConfigurationContext context) { - context.Files.AddIfNotContains("/libs/tui-editor/tui-editor-jquery-patch.js"); context.Files.AddIfNotContains("/libs/to-mark/to-mark.min.js"); if (context.FileProvider.GetFileInfo("/libs/tui-code-snippet/tui-code-snippet.min.js").Exists) @@ -29,7 +28,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor } context.Files.AddIfNotContains("/libs/squire-rte/squire.js"); - context.Files.AddIfNotContains("/libs/tui-editor/tui-editor-Editor.min.js"); + context.Files.AddIfNotContains("/libs/tui-editor/toastui-editor.js"); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/TuiEditor/TuiEditorStyleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/TuiEditor/TuiEditorStyleContributor.cs index 64f818ad6d..a620b77d8a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/TuiEditor/TuiEditorStyleContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/TuiEditor/TuiEditorStyleContributor.cs @@ -14,8 +14,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.TuiEditor { public override void ConfigureBundle(BundleConfigurationContext context) { - context.Files.AddIfNotContains("/libs/tui-editor/tui-editor.min.css"); - context.Files.AddIfNotContains("/libs/tui-editor/tui-editor-contents.min.css"); + context.Files.AddIfNotContains("/libs/tui-editor/toastui-editor.css"); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/TagHelpers/AbpComponentDemoSectionTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/TagHelpers/AbpComponentDemoSectionTagHelper.cs index 328024cc2b..beaa8126fc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/TagHelpers/AbpComponentDemoSectionTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/TagHelpers/AbpComponentDemoSectionTagHelper.cs @@ -120,9 +120,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S return sourceBuilder.ToString(); } - else if (sourceBuilder != null) + else { - sourceBuilder.AppendLine(line); + sourceBuilder?.AppendLine(line); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Toolbars/ToolbarItem.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Toolbars/ToolbarItem.cs index 4676202c24..f7cba501c3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Toolbars/ToolbarItem.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Toolbars/ToolbarItem.cs @@ -1,9 +1,11 @@ using System; +using System.Collections.Generic; using JetBrains.Annotations; +using Volo.Abp.SimpleStateChecking; namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars { - public class ToolbarItem + public class ToolbarItem : IHasSimpleStateCheckers { public Type ComponentType { @@ -15,13 +17,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars public int Order { get; set; } [CanBeNull] + [Obsolete("Use RequirePermissions extension method.")] public string RequiredPermissionName { get; set; } + public List> StateCheckers { get; } + public ToolbarItem([NotNull] Type componentType, int order = 0, string requiredPermissionName = null) { Order = order; ComponentType = Check.NotNull(componentType, nameof(componentType)); RequiredPermissionName = requiredPermissionName; + StateCheckers = new List>(); } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Toolbars/ToolbarManager.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Toolbars/ToolbarManager.cs index 2e97cebecb..53679c5b22 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Toolbars/ToolbarManager.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Toolbars/ToolbarManager.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Mvc.UI.Theming; using Volo.Abp.Authorization.Permissions; using Volo.Abp.DependencyInjection; +using Volo.Abp.SimpleStateChecking; namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars { @@ -15,13 +16,16 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars protected IThemeManager ThemeManager { get; } protected AbpToolbarOptions Options { get; } protected IServiceProvider ServiceProvider { get; } + protected ISimpleStateCheckerManager SimpleStateCheckerManager { get; } public ToolbarManager( IOptions options, IServiceProvider serviceProvider, - IThemeManager themeManager) + IThemeManager themeManager, + ISimpleStateCheckerManager simpleStateCheckerManager) { ThemeManager = themeManager; + SimpleStateCheckerManager = simpleStateCheckerManager; ServiceProvider = serviceProvider; Options = options.Value; } @@ -32,14 +36,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars using (var scope = ServiceProvider.CreateScope()) { - var context = new ToolbarConfigurationContext(ThemeManager.CurrentTheme, toolbar, scope.ServiceProvider); - - foreach (var contributor in Options.Contributors) + using (RequirePermissionsSimpleBatchStateChecker.Use(new RequirePermissionsSimpleBatchStateChecker())) { - await contributor.ConfigureToolbarAsync(context); - } + var context = new ToolbarConfigurationContext(ThemeManager.CurrentTheme, toolbar, scope.ServiceProvider); + + foreach (var contributor in Options.Contributors) + { + await contributor.ConfigureToolbarAsync(context); + } - await CheckPermissionsAsync(scope.ServiceProvider, toolbar); + await CheckPermissionsAsync(scope.ServiceProvider, toolbar); + } } return toolbar; @@ -47,17 +54,20 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars protected virtual async Task CheckPermissionsAsync(IServiceProvider serviceProvider, Toolbar toolbar) { - var requiredPermissionItems = toolbar.Items.Where(x => !x.RequiredPermissionName.IsNullOrWhiteSpace()).ToList(); + foreach (var item in toolbar.Items.Where(x => !x.RequiredPermissionName.IsNullOrWhiteSpace())) + { + item.RequirePermissions(item.RequiredPermissionName); + } - if (requiredPermissionItems.Any()) + var checkPermissionsToolbarItems = toolbar.Items.Where(x => x.StateCheckers.Any()).ToArray(); + if (checkPermissionsToolbarItems.Any()) { - var permissionChecker = serviceProvider.GetRequiredService(); - var grantResult = await permissionChecker.IsGrantedAsync(requiredPermissionItems.Select(x => x.RequiredPermissionName).Distinct().ToArray()); + var result = await SimpleStateCheckerManager.IsEnabledAsync(checkPermissionsToolbarItems); var toBeDeleted = new HashSet(); - foreach (var item in requiredPermissionItems) + foreach (var item in checkPermissionsToolbarItems) { - if (grantResult.Result[item.RequiredPermissionName!] != PermissionGrantResult.Granted) + if (!result[item]) { toBeDeleted.Add(item); } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpActionContextExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpActionContextExtensions.cs index 07b54cc5df..27cfb2feaf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpActionContextExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpActionContextExtensions.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc { - internal static class AbpActionContextExtensions + public static class AbpActionContextExtensions { public static T GetRequiredService(this FilterContext context) where T : class diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinder.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinder.cs index 1916b9aa16..cf2203a8e9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinder.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinder.cs @@ -2,48 +2,28 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Volo.Abp.Timing; namespace Volo.Abp.AspNetCore.Mvc.ModelBinding { public class AbpDateTimeModelBinder : IModelBinder { - private readonly Type _type; - private readonly SimpleTypeModelBinder _simpleTypeModelBinder; + private readonly DateTimeModelBinder _dateTimeModelBinder; private readonly IClock _clock; - public AbpDateTimeModelBinder(ModelBinderProviderContext context) + public AbpDateTimeModelBinder(IClock clock, DateTimeModelBinder dateTimeModelBinder) { - _type = context.Metadata.ModelType; - _clock = context.Services.GetRequiredService(); - _simpleTypeModelBinder = new SimpleTypeModelBinder(context.Metadata.ModelType, - context.Services.GetRequiredService()); + _clock = clock; + _dateTimeModelBinder = dateTimeModelBinder; } public async Task BindModelAsync(ModelBindingContext bindingContext) { - await _simpleTypeModelBinder.BindModelAsync(bindingContext); - - if (!bindingContext.Result.IsModelSet) - { - return; - } - - if (_type == typeof(DateTime)) + await _dateTimeModelBinder.BindModelAsync(bindingContext); + if (bindingContext.Result.IsModelSet && bindingContext.Result.Model is DateTime dateTime) { - var dateTime = (DateTime) bindingContext.Result.Model; bindingContext.Result = ModelBindingResult.Success(_clock.Normalize(dateTime)); } - else - { - var dateTime = (DateTime?) bindingContext.Result.Model; - if (dateTime != null) - { - bindingContext.Result = ModelBindingResult.Success(_clock.Normalize(dateTime.Value)); - } - } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinderProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinderProvider.cs index ddda91c8a0..83129199bc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinderProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ModelBinding/AbpDateTimeModelBinderProvider.cs @@ -1,48 +1,56 @@ using System; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Volo.Abp.Timing; namespace Volo.Abp.AspNetCore.Mvc.ModelBinding { - public class AbpDateTimeModelBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(ModelBinderProviderContext context) { - if (context.Metadata.ModelType != typeof(DateTime) && - context.Metadata.ModelType != typeof(DateTime?)) - { - return null; - } - - if (context.Metadata.ContainerType == null) + var modelType = context.Metadata.UnderlyingOrModelType; + if (modelType == typeof(DateTime)) { - if (context.Metadata is DefaultModelMetadata defaultModelMetadata && - defaultModelMetadata.Attributes.Attributes.All(x => x.GetType() != typeof(DisableDateTimeNormalizationAttribute))) + if (context.Metadata.ContainerType == null) { - return new AbpDateTimeModelBinder(context); + if (context.Metadata is DefaultModelMetadata defaultModelMetadata && + defaultModelMetadata.Attributes.Attributes.All(x => x.GetType() != typeof(DisableDateTimeNormalizationAttribute))) + { + return CreateAbpDateTimeModelBinder(context); + } } - } - else - { - var dateNormalizationDisabledForClass = - context.Metadata.ContainerType.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true); + else + { + var dateNormalizationDisabledForClass = + context.Metadata.ContainerType.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true); - var dateNormalizationDisabledForProperty = context.Metadata.ContainerType - .GetProperty(context.Metadata.PropertyName) - ?.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true); + var dateNormalizationDisabledForProperty = context.Metadata.ContainerType + .GetProperty(context.Metadata.PropertyName) + ?.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true); - if (!dateNormalizationDisabledForClass && - dateNormalizationDisabledForProperty != null && - !dateNormalizationDisabledForProperty.Value) - { - return new AbpDateTimeModelBinder(context); + if (!dateNormalizationDisabledForClass && + dateNormalizationDisabledForProperty != null && + !dateNormalizationDisabledForProperty.Value) + { + return CreateAbpDateTimeModelBinder(context); + } } } return null; } + + protected virtual AbpDateTimeModelBinder CreateAbpDateTimeModelBinder(ModelBinderProviderContext context) + { + const DateTimeStyles supportedStyles = DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AdjustToUniversal; + var dateTimeModelBinder = new DateTimeModelBinder(supportedStyles, context.Services.GetRequiredService()); + return new AbpDateTimeModelBinder(context.Services.GetRequiredService(), dateTimeModelBinder); + } } } diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs index b89e5e9158..6b559f4d3e 100644 --- a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs @@ -30,7 +30,9 @@ namespace Volo.Abp.AspNetCore.SignalR public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddSignalR(); + var signalRServerBuilder = context.Services.AddSignalR(); + + context.Services.ExecutePreConfiguredActions(signalRServerBuilder); Configure(options => { diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/AbpPermissionOptions.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/AbpPermissionOptions.cs index eb2ac920ac..ce9dc06798 100644 --- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/AbpPermissionOptions.cs +++ b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/AbpPermissionOptions.cs @@ -8,13 +8,10 @@ namespace Volo.Abp.Authorization.Permissions public ITypeList ValueProviders { get; } - public ITypeList GlobalStateProviders { get; } - public AbpPermissionOptions() { DefinitionProviders = new TypeList(); ValueProviders = new TypeList(); - GlobalStateProviders = new TypeList(); } } } diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionStateManager.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionStateManager.cs deleted file mode 100644 index 6195e02545..0000000000 --- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionStateManager.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace Volo.Abp.Authorization.Permissions -{ - public interface IPermissionStateManager - { - Task IsEnabledAsync(PermissionDefinition permission); - } -} diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionStateProvider.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionStateProvider.cs deleted file mode 100644 index 7bc3087f50..0000000000 --- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/IPermissionStateProvider.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace Volo.Abp.Authorization.Permissions -{ - public interface IPermissionStateProvider - { - Task IsEnabledAsync(PermissionStateContext context); - } -} diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs index ac525367ad..92eda28b4b 100644 --- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs +++ b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs @@ -3,10 +3,11 @@ using System.Collections.Immutable; using JetBrains.Annotations; using Volo.Abp.Localization; using Volo.Abp.MultiTenancy; +using Volo.Abp.SimpleStateChecking; namespace Volo.Abp.Authorization.Permissions { - public class PermissionDefinition + public class PermissionDefinition : IHasSimpleStateCheckers { /// /// Unique name of the permission. @@ -31,7 +32,7 @@ namespace Volo.Abp.Authorization.Permissions /// public List Providers { get; } //TODO: Rename to AllowedProviders? - public List StateProviders { get; } + public List> StateCheckers { get; } public ILocalizableString DisplayName { @@ -88,7 +89,7 @@ namespace Volo.Abp.Authorization.Permissions Properties = new Dictionary(); Providers = new List(); - StateProviders = new List(); + StateCheckers = new List>(); _children = new List(); } @@ -123,7 +124,7 @@ namespace Volo.Abp.Authorization.Permissions } /// - /// Sets a property in the dictionary. + /// Set the property. /// This is a shortcut for nested calls on this object. /// public virtual PermissionDefinition WithProviders(params string[] providers) diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinitionExtensions.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinitionExtensions.cs deleted file mode 100644 index 7e5de5a1f1..0000000000 --- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/PermissionDefinitionExtensions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using JetBrains.Annotations; - -namespace Volo.Abp.Authorization.Permissions -{ - public static class PermissionDefinitionExtensions - { - public static PermissionDefinition AddStateProviders( - [NotNull] this PermissionDefinition permissionDefinition, - [NotNull] params IPermissionStateProvider[] permissionStateProviders) - { - Check.NotNull(permissionDefinition, nameof(permissionDefinition)); - Check.NotNull(permissionStateProviders, nameof(permissionStateProviders)); - - permissionDefinition.StateProviders.AddRange(permissionStateProviders); - - return permissionDefinition; - } - } -} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/fi.json b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/fi.json new file mode 100644 index 0000000000..16700a0891 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/fi.json @@ -0,0 +1,10 @@ +{ + "culture": "fi", + "texts": { + "Volo.Authorization:010001": "Käyttöoikeuden varmistus epäonnistui! Annettua politiikkaa ei ole myönnetty.", + "Volo.Authorization:010002": "Käyttöoikeuden varmistus epäonnistui! Annettua käytäntöä ei ole myönnetty: {PolicyName}", + "Volo.Authorization:010003": "Käyttöoikeuden varmistus epäonnistui! Annettua käytäntöä ei ole myönnetty tietylle resurssille: {ResourceName}", + "Volo.Authorization:010004": "Käyttöoikeuden varmistus epäonnistui! Annettua vaatimusta ei ole annettu tietylle resurssille: {ResourceName}", + "Volo.Authorization:010005": "Käyttöoikeuden varmistus epäonnistui! Annettuja vaatimuksia ei ole annettu tietylle resurssille: {ResourceName}" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/fr.json b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/fr.json new file mode 100644 index 0000000000..02ab735f7b --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/fr.json @@ -0,0 +1,10 @@ +{ + "culture": "fr", + "texts": { + "Volo.Authorization:010001": "L'autorisation à échouée! Compte tenu de la stratégie n'a été pas accordé.", + "Volo.Authorization:010002": "L'autorisation à échouée! La stratégie donnée n'a pas été accordé: {PolicyName}", + "Volo.Authorization:010003": "L'autorisation à échouée! La stratégie donnée n'a pas été accordée pour une ressource donnée: {ResourceName}", + "Volo.Authorization:010004": "L'autorisation à échouée! L'exigence donnée n'a pas été accordée pour une ressource donnée: {ResourceName}", + "Volo.Authorization:010005": "L'autorisation à échouée! Les exigences données ne sont pas accordées pour une ressource donnée: {ResourceName}" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/hi.json b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/hi.json new file mode 100644 index 0000000000..ee999ca075 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/hi.json @@ -0,0 +1,10 @@ +{ + "culture": "hi", + "texts": { + "Volo.Authorization:010001": "प्रमाणीकरण विफल! दी गई नीति को अनुमति नहीं दी गई है।", + "Volo.Authorization:010002": "प्रमाणीकरण विफल! दी गई नीति को मंजूरी नहीं दी गई है: {PolicyName}", + "Volo.Authorization:010003": "प्रमाणीकरण विफल! दिए गए संसाधन के लिए नीति प्रदान नहीं की गई है: {ResourceName}", + "Volo.Authorization:010004": "प्रमाणीकरण विफल! दिए गए संसाधन के लिए आवश्यकता की अनुमति नहीं दी गई है: {ResourceName}", + "Volo.Authorization:010005": "प्रमाणीकरण विफल! दी गई संसाधन के लिए आवश्यकताओं को पूरा नहीं किया गया है: {ResourceName}" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/it.json b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/it.json new file mode 100644 index 0000000000..422458c820 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/it.json @@ -0,0 +1,10 @@ +{ + "culture": "it", + "texts": { + "Volo.Authorization:010001": "Autorizzazione fallita! Data la politica non ha concesso.", + "Volo.Authorization:010002": "Autorizzazione fallita! La norma data non ha concesso: {PolicyName}", + "Volo.Authorization:010003": "Autorizzazione fallita! La politica data non è stata concessa per una determinata risorsa: {ResourceName}", + "Volo.Authorization:010004": "Autorizzazione fallita! Il requisito dato non è stato concesso per la risorsa data: {ResourceName}", + "Volo.Authorization:010005": "Autorizzazione fallita! I requisiti dati non sono stati concessi per una determinata risorsa: {ResourceName}" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs index d243c9c54c..234fbf7ea2 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionChecker.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; using Volo.Abp.Security.Claims; +using Volo.Abp.SimpleStateChecking; namespace Volo.Abp.Authorization.Permissions { @@ -15,20 +16,20 @@ namespace Volo.Abp.Authorization.Permissions protected ICurrentPrincipalAccessor PrincipalAccessor { get; } protected ICurrentTenant CurrentTenant { get; } protected IPermissionValueProviderManager PermissionValueProviderManager { get; } - protected IPermissionStateManager PermissionStateManager { get; } + protected ISimpleStateCheckerManager StateCheckerManager { get; } public PermissionChecker( ICurrentPrincipalAccessor principalAccessor, IPermissionDefinitionManager permissionDefinitionManager, ICurrentTenant currentTenant, IPermissionValueProviderManager permissionValueProviderManager, - IPermissionStateManager permissionStateManager) + ISimpleStateCheckerManager stateCheckerManager) { PrincipalAccessor = principalAccessor; PermissionDefinitionManager = permissionDefinitionManager; CurrentTenant = currentTenant; PermissionValueProviderManager = permissionValueProviderManager; - PermissionStateManager = permissionStateManager; + StateCheckerManager = stateCheckerManager; } public virtual async Task IsGrantedAsync(string name) @@ -49,7 +50,7 @@ namespace Volo.Abp.Authorization.Permissions return false; } - if (!await PermissionStateManager.IsEnabledAsync(permission)) + if (!await StateCheckerManager.IsEnabledAsync(permission)) { return false; } @@ -112,7 +113,7 @@ namespace Volo.Abp.Authorization.Permissions result.Result.Add(name, PermissionGrantResult.Undefined); if (permission.IsEnabled && - await PermissionStateManager.IsEnabledAsync(permission) && + await StateCheckerManager.IsEnabledAsync(permission) && permission.MultiTenancySide.HasFlag(multiTenancySide)) { permissionDefinitions.Add(permission); diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionSimpleStateCheckerExtensions.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionSimpleStateCheckerExtensions.cs new file mode 100644 index 0000000000..c8c4d315fd --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionSimpleStateCheckerExtensions.cs @@ -0,0 +1,57 @@ +using JetBrains.Annotations; +using Volo.Abp.SimpleStateChecking; + +namespace Volo.Abp.Authorization.Permissions +{ + public static class PermissionSimpleStateCheckerExtensions + { + public static TState RequireAuthenticated([NotNull] this TState state) + where TState : IHasSimpleStateCheckers + { + state.StateCheckers.Add(new RequireAuthenticatedSimpleStateChecker()); + return state; + } + + public static TState RequirePermissions( + [NotNull] this TState state, + params string[] permissions) + where TState : IHasSimpleStateCheckers + { + state.RequirePermissions(requiresAll: true, batchCheck: true, permissions); + return state; + } + + public static TState RequirePermissions( + [NotNull] this TState state, + bool requiresAll, + params string[] permissions) + where TState : IHasSimpleStateCheckers + { + state.RequirePermissions(requiresAll: requiresAll, batchCheck: true, permissions); + return state; + } + + public static TState RequirePermissions( + [NotNull] this TState state, + bool requiresAll, + bool batchCheck, + params string[] permissions) + where TState : IHasSimpleStateCheckers + { + Check.NotNull(state, nameof(state)); + Check.NotNullOrEmpty(permissions, nameof(permissions)); + + if (batchCheck) + { + RequirePermissionsSimpleBatchStateChecker.Current.AddCheckModels(new RequirePermissionsSimpleBatchStateCheckerModel(state, permissions, requiresAll)); + state.StateCheckers.Add(RequirePermissionsSimpleBatchStateChecker.Current); + } + else + { + state.StateCheckers.Add(new RequirePermissionsSimpleStateChecker(new RequirePermissionsSimpleBatchStateCheckerModel(state, permissions, requiresAll))); + } + + return state; + } + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionStateManager.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionStateManager.cs deleted file mode 100644 index 957ed3c7a6..0000000000 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionStateManager.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; - -namespace Volo.Abp.Authorization.Permissions -{ - public class PermissionStateManager : IPermissionStateManager, ITransientDependency - { - protected IServiceProvider ServiceProvider { get; } - protected AbpPermissionOptions Options { get; } - - public PermissionStateManager(IServiceProvider serviceProvider, IOptions options) - { - ServiceProvider = serviceProvider; - Options = options.Value; - } - - public async Task IsEnabledAsync(PermissionDefinition permission) - { - using (var scope = ServiceProvider.CreateScope()) - { - var context = new PermissionStateContext - { - Permission = permission, - ServiceProvider = scope.ServiceProvider.GetRequiredService() - }; - - foreach (var provider in permission.StateProviders) - { - if (!await provider.IsEnabledAsync(context)) - { - return false; - } - } - - foreach (IPermissionStateProvider provider in Options.GlobalStateProviders.Select(x => ServiceProvider.GetRequiredService(x))) - { - if (!await provider.IsEnabledAsync(context)) - { - return false; - } - } - - return true; - } - } - } -} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequireAuthenticatedSimpleStateChecker.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequireAuthenticatedSimpleStateChecker.cs new file mode 100644 index 0000000000..64350bd825 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequireAuthenticatedSimpleStateChecker.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.SimpleStateChecking; +using Volo.Abp.Users; + +namespace Volo.Abp.Authorization.Permissions +{ + public class RequireAuthenticatedSimpleStateChecker : ISimpleStateChecker + where TState : IHasSimpleStateCheckers + { + public Task IsEnabledAsync(SimpleStateCheckerContext context) + { + return Task.FromResult(context.ServiceProvider.GetRequiredService().IsAuthenticated); + } + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleBatchStateChecker.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleBatchStateChecker.cs new file mode 100644 index 0000000000..e03b2b87e3 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleBatchStateChecker.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.SimpleStateChecking; + +namespace Volo.Abp.Authorization.Permissions +{ + public class RequirePermissionsSimpleBatchStateChecker : SimpleBatchStateCheckerBase + where TState : IHasSimpleStateCheckers + { + public static RequirePermissionsSimpleBatchStateChecker Current => _current.Value; + private static readonly AsyncLocal> _current = new AsyncLocal>(); + + private readonly List> _models; + + static RequirePermissionsSimpleBatchStateChecker() + { + _current.Value = new RequirePermissionsSimpleBatchStateChecker(); + } + + public RequirePermissionsSimpleBatchStateChecker() + { + _models = new List>(); + } + + public RequirePermissionsSimpleBatchStateChecker AddCheckModels(params RequirePermissionsSimpleBatchStateCheckerModel[] models) + { + Check.NotNullOrEmpty(models, nameof(models)); + + _models.AddRange(models); + return this; + } + + public static IDisposable Use(RequirePermissionsSimpleBatchStateChecker checker) + { + var previousValue = Current; + _current.Value = checker; + return new DisposeAction(() => _current.Value = previousValue); + } + + public override async Task> IsEnabledAsync(SimpleBatchStateCheckerContext context) + { + var permissionChecker = context.ServiceProvider.GetRequiredService(); + + var result = new SimpleStateCheckerResult(context.States); + + var permissions = _models.Where(x => context.States.Any(s => s.Equals(x.State))).SelectMany(x => x.Permissions).Distinct().ToArray(); + var grantResult = await permissionChecker.IsGrantedAsync(permissions); + + foreach (var state in context.States) + { + var model = _models.FirstOrDefault(x => x.State.Equals(state)); + if (model != null) + { + if (model.RequiresAll) + { + result[model.State] = model.Permissions.All(x => grantResult.Result.Any(y => y.Key == x && y.Value == PermissionGrantResult.Granted)); + } + else + { + result[model.State] = grantResult.Result.Any(x => model.Permissions.Contains(x.Key) && x.Value == PermissionGrantResult.Granted); + } + } + } + + return result; + } + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleBatchStateCheckerModel.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleBatchStateCheckerModel.cs new file mode 100644 index 0000000000..3660d10f46 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleBatchStateCheckerModel.cs @@ -0,0 +1,24 @@ +using Volo.Abp.SimpleStateChecking; + +namespace Volo.Abp.Authorization.Permissions +{ + public class RequirePermissionsSimpleBatchStateCheckerModel + where TState : IHasSimpleStateCheckers + { + public TState State { get; } + + public string[] Permissions { get; } + + public bool RequiresAll { get; } + + public RequirePermissionsSimpleBatchStateCheckerModel(TState state, string[] permissions, bool requiresAll = true) + { + Check.NotNull(state, nameof(state)); + Check.NotNullOrEmpty(permissions, nameof(permissions)); + + State = state; + Permissions = permissions; + RequiresAll = requiresAll; + } + } +} diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleStateChecker.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleStateChecker.cs new file mode 100644 index 0000000000..32cedeecc6 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RequirePermissionsSimpleStateChecker.cs @@ -0,0 +1,34 @@ +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.SimpleStateChecking; + +namespace Volo.Abp.Authorization.Permissions +{ + public class RequirePermissionsSimpleStateChecker : ISimpleStateChecker + where TState : IHasSimpleStateCheckers + { + private readonly RequirePermissionsSimpleBatchStateCheckerModel _model; + + public RequirePermissionsSimpleStateChecker(RequirePermissionsSimpleBatchStateCheckerModel model) + { + _model = model; + } + + public async Task IsEnabledAsync(SimpleStateCheckerContext context) + { + var permissionChecker = context.ServiceProvider.GetRequiredService(); + + if (_model.Permissions.Length == 1) + { + return await permissionChecker.IsGrantedAsync(_model.Permissions.First()); + } + + var grantResult = await permissionChecker.IsGrantedAsync(_model.Permissions); + + return _model.RequiresAll + ? grantResult.AllGranted + : grantResult.Result.Any(x => _model.Permissions.Contains(x.Key) && x.Value == PermissionGrantResult.Granted); + } + } +} diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs index 96caf956b1..776a8b9a7a 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs @@ -35,7 +35,11 @@ namespace Autofac.Builder return registrationBuilder; } - private static IRegistrationBuilder InvokeRegistrationActions(this IRegistrationBuilder registrationBuilder, ServiceRegistrationActionList registrationActionList, Type serviceType, Type implementationType) + private static IRegistrationBuilder InvokeRegistrationActions( + this IRegistrationBuilder registrationBuilder, + ServiceRegistrationActionList registrationActionList, + Type serviceType, + Type implementationType) where TActivatorData : ReflectionActivatorData { var serviceRegistredArgs = new OnServiceRegistredContext(serviceType, implementationType); @@ -48,6 +52,7 @@ namespace Autofac.Builder if (serviceRegistredArgs.Interceptors.Any()) { registrationBuilder = registrationBuilder.AddInterceptors( + registrationActionList, serviceType, serviceRegistredArgs.Interceptors ); @@ -71,10 +76,12 @@ namespace Autofac.Builder return registrationBuilder; } - private static IRegistrationBuilder AddInterceptors( - this IRegistrationBuilder registrationBuilder, - Type serviceType, - IEnumerable interceptors) + private static IRegistrationBuilder + AddInterceptors( + this IRegistrationBuilder registrationBuilder, + ServiceRegistrationActionList serviceRegistrationActionList, + Type serviceType, + IEnumerable interceptors) where TActivatorData : ReflectionActivatorData { if (serviceType.IsInterface) @@ -83,6 +90,11 @@ namespace Autofac.Builder } else { + if (serviceRegistrationActionList.IsClassInterceptorsDisabled) + { + return registrationBuilder; + } + (registrationBuilder as IRegistrationBuilder)?.EnableClassInterceptors(); } diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs index 0b75f389fe..a37807e473 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerAdapter.cs @@ -75,10 +75,7 @@ namespace Volo.Abp.BackgroundWorkers.Quartz } case PeriodicBackgroundWorkerBase syncWorker: { - if (_doWorkMethod != null) - { - _doWorkMethod.Invoke(syncWorker, new object[] {workerContext}); - } + _doWorkMethod?.Invoke(syncWorker, new object[] {workerContext}); break; } diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs index 6ce4a10a53..19ace62aca 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs @@ -485,16 +485,26 @@ namespace Volo.Abp.BlazoriseUI try { await CheckDeletePolicyAsync(); - + await OnDeletingEntityAsync(); await AppService.DeleteAsync(entity.Id); - await GetEntitiesAsync(); - await InvokeAsync(StateHasChanged); + await OnDeletedEntityAsync(); } catch (Exception ex) { await HandleErrorAsync(ex); } } + + protected virtual Task OnDeletingEntityAsync() + { + return Task.CompletedTask; + } + + protected virtual async Task OnDeletedEntityAsync() + { + await GetEntitiesAsync(); + await InvokeAsync(StateHasChanged); + } protected virtual string GetDeleteConfirmationMessage(TListViewModel entity) { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs index 330cbeb77a..b3de9d71ff 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs @@ -29,6 +29,7 @@ namespace Volo.Abp.Cli { //TODO: Define constants like done for GenerateProxyCommand.Name. options.Commands["help"] = typeof(HelpCommand); + options.Commands["prompt"] = typeof(PromptCommand); options.Commands["new"] = typeof(NewCommand); options.Commands["get-source"] = typeof(GetSourceCommand); options.Commands["update"] = typeof(UpdateCommand); @@ -36,6 +37,7 @@ namespace Volo.Abp.Cli options.Commands["add-module"] = typeof(AddModuleCommand); options.Commands["list-modules"] = typeof(ListModulesCommand); options.Commands["login"] = typeof(LoginCommand); + options.Commands["login-info"] = typeof(LoginInfoCommand); options.Commands["logout"] = typeof(LogoutCommand); options.Commands[GenerateProxyCommand.Name] = typeof(GenerateProxyCommand); options.Commands[RemoveProxyCommand.Name] = typeof(RemoveProxyCommand); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Args/CommandLineArgumentParser.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Args/CommandLineArgumentParser.cs index 1dd29e5df7..b7cd95a3e0 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Args/CommandLineArgumentParser.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Args/CommandLineArgumentParser.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Cli.Args @@ -71,6 +72,11 @@ namespace Volo.Abp.Cli.Args return commandLineArgs; } + public CommandLineArgs Parse(string lineText) + { + return Parse(GetArgsArrayFromLine(lineText)); + } + private static bool IsOptionName(string argument) { return argument.StartsWith("-") || argument.StartsWith("--"); @@ -100,5 +106,46 @@ namespace Volo.Abp.Cli.Args throw new ArgumentException("Option names should start with '-' or '--'."); } + + private static string[] GetArgsArrayFromLine(string lineText) + { + var args = new List(); + var currentArgBuilder = new StringBuilder(); + string currentArg = null; + bool isInQuotes = false; + for (int i = 0; i < lineText.Length; i++) + { + var c = lineText[i]; + if (c == ' ' && !isInQuotes) + { + currentArg = currentArgBuilder.ToString(); + if (!currentArg.IsNullOrWhiteSpace()) + { + args.Add(currentArg); + } + + currentArgBuilder = new StringBuilder(); + } + else + { + if (c == '\"') + { + isInQuotes = !isInQuotes; + } + else + { + currentArgBuilder.Append(c); + } + } + } + + currentArg = currentArgBuilder.ToString(); + if (!currentArg.IsNullOrWhiteSpace()) + { + args.Add(currentArg); + } + + return args.ToArray(); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Args/ICommandLineArgumentParser.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Args/ICommandLineArgumentParser.cs index c467541210..4e8ee7cd77 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Args/ICommandLineArgumentParser.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Args/ICommandLineArgumentParser.cs @@ -3,5 +3,7 @@ public interface ICommandLineArgumentParser { CommandLineArgs Parse(string[] args); + + CommandLineArgs Parse(string lineText); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs index f3cb291f56..bb16733e16 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/AuthService.cs @@ -1,21 +1,73 @@ using System; using System.IO; +using System.Net.Http; using System.Text; +using System.Text.Json; +using System.Threading; using System.Threading.Tasks; using IdentityModel; +using Microsoft.Extensions.Logging; +using Volo.Abp.Cli.Commands; +using Volo.Abp.Cli.Http; +using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.DependencyInjection; using Volo.Abp.IdentityModel; -using Volo.Abp.IO; +using Volo.Abp.Json; +using Volo.Abp.Threading; namespace Volo.Abp.Cli.Auth { public class AuthService : ITransientDependency { protected IIdentityModelAuthenticationService AuthenticationService { get; } + protected ILogger Logger { get; } + protected CliHttpClientFactory CliHttpClientFactory { get; } + public RemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } + public IJsonSerializer JsonSerializer { get; } + public ICancellationTokenProvider CancellationTokenProvider { get; } - public AuthService(IIdentityModelAuthenticationService authenticationService) + public AuthService( + IIdentityModelAuthenticationService authenticationService, + ILogger logger, + ICancellationTokenProvider cancellationTokenProvider, + CliHttpClientFactory cliHttpClientFactory, + RemoteServiceExceptionHandler remoteServiceExceptionHandler, + IJsonSerializer jsonSerializer + ) { AuthenticationService = authenticationService; + Logger = logger; + CancellationTokenProvider = cancellationTokenProvider; + CliHttpClientFactory = cliHttpClientFactory; + RemoteServiceExceptionHandler = remoteServiceExceptionHandler; + JsonSerializer = jsonSerializer; + } + + public async Task GetLoginInfoAsync() + { + if (!IsLoggedIn()) + { + return null; + } + + var url = $"{CliUrls.WwwAbpIo}api/license/login-info"; + + var client = CliHttpClientFactory.CreateClient(); + + using (var response = await client.GetHttpResponseMessageWithRetryAsync(url, CancellationTokenProvider.Token, Logger)) + { + if (!response.IsSuccessStatusCode) + { + Logger.LogError("Remote server returns '{response.StatusCode}'"); + return null; + } + + await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); + + var responseContent = await response.Content.ReadAsStringAsync(); + + return JsonSerializer.Deserialize(responseContent); + } } public async Task LoginAsync(string userName, string password, string organizationName = null) @@ -40,11 +92,50 @@ namespace Volo.Abp.Cli.Auth File.WriteAllText(CliPaths.AccessToken, accessToken, Encoding.UTF8); } - public Task LogoutAsync() + public async Task LogoutAsync() { - FileHelper.DeleteIfExists(CliPaths.AccessToken); - FileHelper.DeleteIfExists(CliPaths.Lic); - return Task.CompletedTask; + string accessToken = null; + if (File.Exists(CliPaths.AccessToken)) + { + accessToken = File.ReadAllText(CliPaths.AccessToken); + File.Delete(CliPaths.AccessToken); + } + + if (File.Exists(CliPaths.Lic)) + { + if (!string.IsNullOrWhiteSpace(accessToken)) + { + await LogoutAsync(accessToken); + } + + File.Delete(CliPaths.Lic); + } + } + + private async Task LogoutAsync(string accessToken) + { + try + { + var client = CliHttpClientFactory.CreateClient(); + var content = new StringContent( + JsonSerializer.Serialize(new {token = accessToken}), + Encoding.UTF8, "application/json" + ); + + using (var response = await client.PostAsync(CliConsts.LogoutUrl, content, CancellationTokenProvider.Token)) + { + if (!response.IsSuccessStatusCode) + { + Logger.LogWarning( + $"Cannot logout from remote service! Response: {response.StatusCode}-{response.ReasonPhrase}" + ); + } + } + } + catch (Exception e) + { + Logger.LogWarning($"Error occured while logging out from remote service. {e.Message}"); + } } public static bool IsLoggedIn() diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/LoginInfo.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/LoginInfo.cs new file mode 100644 index 0000000000..2ad31421e5 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/LoginInfo.cs @@ -0,0 +1,16 @@ + +namespace Volo.Abp.Cli.Auth +{ + public class LoginInfo + { + public string Name { get; set; } + + public string Surname { get; set; } + + public string Username { get; set; } + + public string EmailAddress { get; set; } + + public string Organization { get; set; } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlerBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlerBase.cs index 97ef628d5a..074b7f6980 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlerBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlerBase.cs @@ -75,7 +75,7 @@ namespace Volo.Abp.Cli.Bundling var pathFragments = definition.Source.Split('/').ToList(); var basePath = $"{pathFragments[0]}/{pathFragments[1]}"; var node = staticAssetsDefinitions.SelectSingleNode($"//ContentRoot[@BasePath='{basePath}']"); - if (node == null || node.Attributes == null) + if (node?.Attributes == null) { throw new AbpException("Not found: " + definition.Source); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs index 37dbbba318..77fa3b8236 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs @@ -9,5 +9,7 @@ public const string DocsLink = "https://docs.abp.io"; public const string HttpClientName = "AbpHttpClient"; + + public const string LogoutUrl = CliUrls.WwwAbpIo + "api/license/logout"; } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs index 785d2ff3fc..a418ceba52 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs @@ -3,9 +3,11 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using NuGet.Versioning; using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using System.Text; using System.Threading.Tasks; using Volo.Abp.Cli.Args; using Volo.Abp.Cli.Commands; @@ -40,23 +42,64 @@ namespace Volo.Abp.Cli public async Task RunAsync(string[] args) { Logger.LogInformation("ABP CLI (https://abp.io)"); - + var commandLineArgs = CommandLineArgumentParser.Parse(args); +#if !DEBUG if (!commandLineArgs.Options.ContainsKey("skip-cli-version-check")) { await CheckCliVersionAsync(); } +#endif + try + { + if (commandLineArgs.IsCommand("prompt")) + { + await RunPromptAsync(); + } + else if (commandLineArgs.IsCommand("batch")) + { + await RunBatchAsync(commandLineArgs); + } + else + { + await RunInternalAsync(commandLineArgs); + } + } + catch (CliUsageException usageException) + { + Logger.LogWarning(usageException.Message); + } + catch (Exception ex) + { + Logger.LogException(ex); + } + } - var commandType = CommandSelector.Select(commandLineArgs); - - using (var scope = ServiceScopeFactory.CreateScope()) + private async Task RunPromptAsync() + { + string GetPromptInput() { - var command = (IConsoleCommand)scope.ServiceProvider.GetRequiredService(commandType); + Console.WriteLine("Enter the command to execute or `exit` to exit the prompt model"); + Console.Write("> "); + return Console.ReadLine(); + } + var promptInput = GetPromptInput(); + do + { try { - await command.ExecuteAsync(commandLineArgs); + var commandLineArgs = CommandLineArgumentParser.Parse(promptInput.Split(" ").Where(x => !x.IsNullOrWhiteSpace()).ToArray()); + + if (commandLineArgs.IsCommand("batch")) + { + await RunBatchAsync(commandLineArgs); + } + else + { + await RunInternalAsync(commandLineArgs); + } } catch (CliUsageException usageException) { @@ -66,6 +109,53 @@ namespace Volo.Abp.Cli { Logger.LogException(ex); } + + promptInput = GetPromptInput(); + + } while (promptInput?.ToLower() != "exit"); + } + + private async Task RunBatchAsync(CommandLineArgs commandLineArgs) + { + var targetFile = commandLineArgs.Target; + if (targetFile.IsNullOrWhiteSpace()) + { + throw new CliUsageException( + "Must provide a file name/path that contains a list of commands" + + Environment.NewLine + Environment.NewLine + + "Example: " + + " abp batch commands.txt" + ); + } + + var filePath = Path.Combine(Directory.GetCurrentDirectory(), targetFile); + var fileLines = File.ReadAllLines(filePath); + foreach (var line in fileLines) + { + var lineText = line; + if (lineText.IsNullOrWhiteSpace() || lineText.StartsWith("#")) + { + continue; + } + + if (lineText.Contains('#')) + { + lineText = lineText.Substring(0, lineText.IndexOf('#')); + } + + var args = CommandLineArgumentParser.Parse(lineText); + await RunInternalAsync(args); + } + } + + private async Task RunInternalAsync(CommandLineArgs commandLineArgs) + { + var commandType = CommandSelector.Select(commandLineArgs); + + using (var scope = ServiceScopeFactory.CreateScope()) + { + var command = (IConsoleCommand) scope.ServiceProvider.GetRequiredService(commandType); + await command.ExecuteAsync(commandLineArgs); } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginInfoCommand..cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginInfoCommand..cs new file mode 100644 index 0000000000..e5bd62c393 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginInfoCommand..cs @@ -0,0 +1,63 @@ +using System; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Auth; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Cli.Commands +{ + public class LoginInfoCommand : IConsoleCommand, ITransientDependency + { + public ILogger Logger { get; set; } + + protected AuthService AuthService { get; } + + public LoginInfoCommand(AuthService authService) + { + AuthService = authService; + Logger = NullLogger.Instance; + } + + public async Task ExecuteAsync(CommandLineArgs commandLineArgs) + { + var loginInfo = await AuthService.GetLoginInfoAsync(); + + if (loginInfo == null) + { + Logger.LogError("Unable to get login info."); + return; + } + + var sb = new StringBuilder(); + sb.AppendLine(""); + sb.AppendLine($"Login info:"); + sb.AppendLine($"Name: {loginInfo.Name}"); + sb.AppendLine($"Surname: {loginInfo.Surname}"); + sb.AppendLine($"Username: {loginInfo.Username}"); + sb.AppendLine($"Email Address: {loginInfo.EmailAddress}"); + sb.AppendLine($"Organization: {loginInfo.Organization}"); + Logger.LogInformation(sb.ToString()); + } + + public string GetUsageInfo() + { + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(" abp login-info"); + sb.AppendLine(""); + sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); + + return sb.ToString(); + } + + public string GetShortDescription() + { + return "Show your login info."; + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 83cce36fce..c8757e1252 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -61,6 +61,11 @@ namespace Volo.Abp.Cli.Commands ); } + if (!ProjectNameValidator.IsValid(projectName)) + { + throw new CliUsageException("The project name is invalid! Please specify a different name."); + } + Logger.LogInformation("Creating your project..."); Logger.LogInformation("Project name: " + projectName); @@ -554,4 +559,4 @@ namespace Volo.Abp.Cli.Commands } } } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/PromptCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/PromptCommand.cs new file mode 100644 index 0000000000..f6258c4b12 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/PromptCommand.cs @@ -0,0 +1,33 @@ +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Cli.Args; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Cli.Commands +{ + public class PromptCommand : IConsoleCommand, ITransientDependency + { + public Task ExecuteAsync(CommandLineArgs commandLineArgs) + { + return Task.CompletedTask; + } + + public string GetUsageInfo() + { + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(" abp prompt"); + sb.AppendLine(""); + sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); + + return sb.ToString(); + } + + public string GetShortDescription() + { + return "Starts with prompt mode."; + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/ConnectionStringProvider.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/ConnectionStringProvider.cs index 2e53f6a84c..e4c5394a60 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/ConnectionStringProvider.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/ConnectionStringProvider.cs @@ -16,12 +16,12 @@ namespace Volo.Abp.Cli.Commands.Services case DatabaseManagementSystem.MySQL: return "Server=localhost;Port=3306;Database=MyProjectName;Uid=root;Pwd=myPassword;"; case DatabaseManagementSystem.PostgreSQL: - return "Host=localhost;Port=5432;Database=MyProjectName;User ID=root;Password=myPassword;Pooling=true;MinimumPoolSize=0;MaximumPoolSize=100;Connection Lifetime=0;"; + return "Host=localhost;Port=5432;Database=MyProjectName;User ID=root;Password=myPassword;"; case DatabaseManagementSystem.Oracle: case DatabaseManagementSystem.OracleDevart: return "Data Source=MyProjectName;Integrated Security=yes;"; case DatabaseManagementSystem.SQLite: - return $"Data Source={Path.Combine(outputFolder , "MyProjectName.db")};".Replace("\\", "\\\\"); + return $"Data Source={Path.Combine(outputFolder, "MyProjectName.db")};".Replace("\\", "\\\\"); default: return null; } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs index 612f3b7234..34cde45265 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs @@ -275,6 +275,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine(" abp suite"); sb.AppendLine(" abp suite install"); sb.AppendLine(" abp suite install --preview"); + sb.AppendLine(" abp suite install --version 4.2.2"); sb.AppendLine(" abp suite update"); sb.AppendLine(" abp suite update --preview"); sb.AppendLine(" abp suite remove"); @@ -303,4 +304,4 @@ namespace Volo.Abp.Cli.Commands } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ProjectNameValidator.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ProjectNameValidator.cs new file mode 100644 index 0000000000..8430cd79a0 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ProjectNameValidator.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.Cli.Utils +{ + public static class ProjectNameValidator + { + private static readonly string[] IllegalProjectNames = new[] + { + "MyCompanyName.MyProjectName", + "MyProjectName", + "CON", //Windows doesn't accept these names as file name + "AUX", + "PRN", + "COM1", + "LPT2" + }; + + private static bool HasParentDirectoryString(string projectName) + { + return projectName.Contains(".."); + } + + private static bool HasSurrogateOrControlChar(string projectName) + { + return projectName.Any(chr => char.IsControl(chr) || char.IsSurrogate(chr)); + } + + private static bool IsIllegalProjectName(string projectName) + { + foreach (var illegalProjectName in IllegalProjectNames) + { + if (projectName.Equals(illegalProjectName, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + + public static bool IsValid(string projectName) + { + if (projectName == null) + { + throw new CliUsageException("Project name cannot be empty!"); + } + + if (HasSurrogateOrControlChar(projectName)) + { + return false; + } + + if (HasParentDirectoryString(projectName)) + { + return false; + } + + if (IsIllegalProjectName(projectName)) + { + return false; + } + + return true; + } + } +} diff --git a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Program.cs b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Program.cs index 886520e95c..e3222fdb84 100644 --- a/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Program.cs +++ b/framework/src/Volo.Abp.Cli/Volo/Abp/Cli/Program.cs @@ -40,8 +40,10 @@ namespace Volo.Abp.Cli await application.ServiceProvider .GetRequiredService() .RunAsync(args); - + application.Shutdown(); + + Log.CloseAndFlush(); } } } diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs index 59cbdec860..41676f00d5 100644 --- a/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs +++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs @@ -28,6 +28,16 @@ namespace Microsoft.Extensions.DependencyInjection return actionList; } + + public static void DisableAbpClassInterceptors(this IServiceCollection services) + { + GetOrCreateRegistrationActionList(services).IsClassInterceptorsDisabled = true; + } + + public static bool IsAbpClassInterceptorsDisabled(this IServiceCollection services) + { + return GetOrCreateRegistrationActionList(services).IsClassInterceptorsDisabled; + } // OnExposing diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs index 58f75f3b96..df732e9bbc 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithExternalServiceProvider.cs @@ -18,7 +18,24 @@ namespace Volo.Abp services.AddSingleton(this); } - public void Initialize(IServiceProvider serviceProvider) + void IAbpApplicationWithExternalServiceProvider.SetServiceProvider([NotNull] IServiceProvider serviceProvider) + { + Check.NotNull(serviceProvider, nameof(serviceProvider)); + + if (ServiceProvider != null) + { + if (ServiceProvider != serviceProvider) + { + throw new AbpException("Service provider was already set before to another service provider instance."); + } + + return; + } + + SetServiceProvider(serviceProvider); + } + + public void Initialize([NotNull] IServiceProvider serviceProvider) { Check.NotNull(serviceProvider, nameof(serviceProvider)); diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs index 2ba93dd513..8429a00bcc 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationWithInternalServiceProvider.cs @@ -31,11 +31,22 @@ namespace Volo.Abp Services.AddSingleton(this); } - public void Initialize() + public IServiceProvider CreateServiceProvider() { + if (ServiceProvider != null) + { + return ServiceProvider; + } + ServiceScope = Services.BuildServiceProviderFromFactory().CreateScope(); SetServiceProvider(ServiceScope.ServiceProvider); + return ServiceProvider; + } + + public void Initialize() + { + CreateServiceProvider(); InitializeModules(); } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ServiceRegistrationActionList.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ServiceRegistrationActionList.cs index bb72d28929..19ab6cdba2 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ServiceRegistrationActionList.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ServiceRegistrationActionList.cs @@ -5,6 +5,6 @@ namespace Volo.Abp.DependencyInjection { public class ServiceRegistrationActionList : List> { - + public bool IsClassInterceptorsDisabled { get; set; } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs index 8968fdf918..fcff07fc66 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs @@ -5,6 +5,16 @@ namespace Volo.Abp { public interface IAbpApplicationWithExternalServiceProvider : IAbpApplication { + /// + /// Sets the service provider, but not initializes the modules. + /// + void SetServiceProvider([NotNull] IServiceProvider serviceProvider); + + /// + /// Sets the service provider and initializes all the modules. + /// If was called before, the same + /// instance should be passed to this method. + /// void Initialize([NotNull] IServiceProvider serviceProvider); } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithInternalServiceProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithInternalServiceProvider.cs index b598535292..78d2829489 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithInternalServiceProvider.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithInternalServiceProvider.cs @@ -1,7 +1,20 @@ -namespace Volo.Abp +using System; + +namespace Volo.Abp { public interface IAbpApplicationWithInternalServiceProvider : IAbpApplication { + /// + /// Creates the service provider, but not initializes the modules. + /// Multiple calls returns the same service provider without creating again. + /// + IServiceProvider CreateServiceProvider(); + + /// + /// Creates the service provider and initializes all the modules. + /// If method was called before, + /// it does not re-create it, but uses the previous one. + /// void Initialize(); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/InternalServiceCollectionExtensions.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/InternalServiceCollectionExtensions.cs index ee06003204..5c729b4197 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/InternalServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/InternalServiceCollectionExtensions.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Logging; using Volo.Abp.Modularity; using Volo.Abp.Reflection; +using Volo.Abp.SimpleStateChecking; namespace Volo.Abp.Internal { @@ -40,6 +41,8 @@ namespace Volo.Abp.Internal services.AddAssemblyOf(); + services.AddTransient(typeof(ISimpleStateCheckerManager<>), typeof(SimpleStateCheckerManager<>)); + services.Configure(options => { options.Contributors.Add(); diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs index e8bccb8e18..286001345d 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs @@ -12,7 +12,7 @@ namespace Volo.Abp.Modularity { var moduleTypes = new List(); logger.Log(LogLevel.Information, "Loaded ABP modules:"); - AddModuleAndDependenciesResursively(moduleTypes, startupModuleType, logger); + AddModuleAndDependenciesRecursively(moduleTypes, startupModuleType, logger); return moduleTypes; } @@ -37,7 +37,7 @@ namespace Volo.Abp.Modularity return dependencies; } - private static void AddModuleAndDependenciesResursively( + private static void AddModuleAndDependenciesRecursively( List moduleTypes, Type moduleType, ILogger logger, @@ -55,7 +55,7 @@ namespace Volo.Abp.Modularity foreach (var dependedModuleType in FindDependedModuleTypes(moduleType)) { - AddModuleAndDependenciesResursively(moduleTypes, dependedModuleType, logger, depth + 1); + AddModuleAndDependenciesRecursively(moduleTypes, dependedModuleType, logger, depth + 1); } } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/AbpSimpleStateCheckerOptions.cs b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/AbpSimpleStateCheckerOptions.cs new file mode 100644 index 0000000000..66201449a1 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/AbpSimpleStateCheckerOptions.cs @@ -0,0 +1,15 @@ +using Volo.Abp.Collections; + +namespace Volo.Abp.SimpleStateChecking +{ + public class AbpSimpleStateCheckerOptions + where TState : IHasSimpleStateCheckers + { + public ITypeList> GlobalStateCheckers { get; } + + public AbpSimpleStateCheckerOptions() + { + GlobalStateCheckers = new TypeList>(); + } + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/IHasSimpleStateCheckers.cs b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/IHasSimpleStateCheckers.cs new file mode 100644 index 0000000000..b9548e3bf4 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/IHasSimpleStateCheckers.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Volo.Abp.SimpleStateChecking +{ + public interface IHasSimpleStateCheckers + where TState : IHasSimpleStateCheckers + { + List> StateCheckers { get; } + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/ISimpleBatchStateChecker.cs b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/ISimpleBatchStateChecker.cs new file mode 100644 index 0000000000..ff364ff223 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/ISimpleBatchStateChecker.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.SimpleStateChecking +{ + public interface ISimpleBatchStateChecker : ISimpleStateChecker + where TState : IHasSimpleStateCheckers + { + Task> IsEnabledAsync(SimpleBatchStateCheckerContext context); + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/ISimpleStateChecker.cs b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/ISimpleStateChecker.cs new file mode 100644 index 0000000000..6d50044520 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/ISimpleStateChecker.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.SimpleStateChecking +{ + public interface ISimpleStateChecker + where TState : IHasSimpleStateCheckers + { + Task IsEnabledAsync(SimpleStateCheckerContext context); + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/ISimpleStateCheckerManager.cs b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/ISimpleStateCheckerManager.cs new file mode 100644 index 0000000000..4ea98f7e68 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/ISimpleStateCheckerManager.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.SimpleStateChecking +{ + public interface ISimpleStateCheckerManager + where TState : IHasSimpleStateCheckers + { + Task IsEnabledAsync(TState state); + + Task> IsEnabledAsync(TState[] states); + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleBatchStateCheckerBase.cs b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleBatchStateCheckerBase.cs new file mode 100644 index 0000000000..43b2e2a6fe --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleBatchStateCheckerBase.cs @@ -0,0 +1,16 @@ +using System.Linq; +using System.Threading.Tasks; + +namespace Volo.Abp.SimpleStateChecking +{ + public abstract class SimpleBatchStateCheckerBase: ISimpleBatchStateChecker + where TState : IHasSimpleStateCheckers + { + public async Task IsEnabledAsync(SimpleStateCheckerContext context) + { + return (await IsEnabledAsync(new SimpleBatchStateCheckerContext(context.ServiceProvider, new[] {context.State}))).Values.All(x => x); + } + + public abstract Task> IsEnabledAsync(SimpleBatchStateCheckerContext context); + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleBatchStateCheckerContext.cs b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleBatchStateCheckerContext.cs new file mode 100644 index 0000000000..ae5826a3e1 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleBatchStateCheckerContext.cs @@ -0,0 +1,18 @@ +using System; + +namespace Volo.Abp.SimpleStateChecking +{ + public class SimpleBatchStateCheckerContext + where TState : IHasSimpleStateCheckers + { + public IServiceProvider ServiceProvider { get; } + + public TState[] States { get; } + + public SimpleBatchStateCheckerContext(IServiceProvider serviceProvider, TState[] states) + { + ServiceProvider = serviceProvider; + States = states; + } + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleStateCheckerContext.cs b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleStateCheckerContext.cs new file mode 100644 index 0000000000..04e9da4720 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleStateCheckerContext.cs @@ -0,0 +1,18 @@ +using System; + +namespace Volo.Abp.SimpleStateChecking +{ + public class SimpleStateCheckerContext + where TState : IHasSimpleStateCheckers + { + public IServiceProvider ServiceProvider { get; } + + public TState State { get; } + + public SimpleStateCheckerContext(IServiceProvider serviceProvider, TState state) + { + ServiceProvider = serviceProvider; + State = state; + } + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleStateCheckerManager.cs b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleStateCheckerManager.cs new file mode 100644 index 0000000000..61a252850d --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleStateCheckerManager.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.SimpleStateChecking +{ + public class SimpleStateCheckerManager : ISimpleStateCheckerManager + where TState : IHasSimpleStateCheckers + { + protected IServiceProvider ServiceProvider { get; } + + protected AbpSimpleStateCheckerOptions Options { get; } + + public SimpleStateCheckerManager(IServiceProvider serviceProvider, IOptions> options) + { + ServiceProvider = serviceProvider; + Options = options.Value; + } + + public virtual async Task IsEnabledAsync(TState state) + { + return await InternalIsEnabledAsync(state, true); + } + + public virtual async Task> IsEnabledAsync(TState[] states) + { + var result = new SimpleStateCheckerResult(states); + + using (var scope = ServiceProvider.CreateScope()) + { + var batchStateCheckers = states.SelectMany(x => x.StateCheckers) + .Where(x => x is ISimpleBatchStateChecker) + .Cast>() + .GroupBy(x => x) + .Select(x => x.Key); + + foreach (var stateChecker in batchStateCheckers) + { + var context = new SimpleBatchStateCheckerContext( + scope.ServiceProvider.GetRequiredService(), + states.Where(x => x.StateCheckers.Contains(stateChecker)).ToArray()); + + foreach (var x in await stateChecker.IsEnabledAsync(context)) + { + result[x.Key] = x.Value; + } + + if (result.Values.All(x => !x)) + { + return result; + } + } + + foreach (ISimpleBatchStateChecker globalStateChecker in Options.GlobalStateCheckers + .Where(x => typeof(ISimpleBatchStateChecker).IsAssignableFrom(x)) + .Select(x => ServiceProvider.GetRequiredService(x))) + { + var context = new SimpleBatchStateCheckerContext( + scope.ServiceProvider.GetRequiredService(), + states.Where(x => result.Any(y => y.Key.Equals(x) && y.Value)).ToArray()); + + foreach (var x in await globalStateChecker.IsEnabledAsync(context)) + { + result[x.Key] = x.Value; + } + } + + foreach (var state in states) + { + if (result[state]) + { + result[state] = await InternalIsEnabledAsync(state, false); + } + } + + return result; + } + } + + protected virtual async Task InternalIsEnabledAsync(TState state, bool useBatchChecker) + { + using (var scope = ServiceProvider.CreateScope()) + { + var context = new SimpleStateCheckerContext(scope.ServiceProvider.GetRequiredService(), state); + + foreach (var provider in state.StateCheckers.WhereIf(!useBatchChecker, x => x is not ISimpleBatchStateChecker)) + { + if (!await provider.IsEnabledAsync(context)) + { + return false; + } + } + + foreach (ISimpleStateChecker provider in Options.GlobalStateCheckers + .WhereIf(!useBatchChecker, x => !typeof(ISimpleBatchStateChecker).IsAssignableFrom(x)) + .Select(x => ServiceProvider.GetRequiredService(x))) + { + if (!await provider.IsEnabledAsync(context)) + { + return false; + } + } + + return true; + } + } + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleStateCheckerResult.cs b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleStateCheckerResult.cs new file mode 100644 index 0000000000..a3c1dc8020 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/SimpleStateChecking/SimpleStateCheckerResult.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace Volo.Abp.SimpleStateChecking +{ + public class SimpleStateCheckerResult : Dictionary + where TState : IHasSimpleStateCheckers + { + public SimpleStateCheckerResult() + { + + } + + public SimpleStateCheckerResult(IEnumerable states, bool initValue = true) + { + foreach (var state in states) + { + Add(state, initValue); + } + } + } +} diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolverExtensions.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolverExtensions.cs index 1fa097964c..ceeaec8f8f 100644 --- a/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolverExtensions.cs +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringResolverExtensions.cs @@ -10,13 +10,26 @@ namespace Volo.Abp.Data [Obsolete("Use ResolveAsync method")] public static string Resolve(this IConnectionStringResolver resolver) { - return resolver.Resolve(ConnectionStringNameAttribute.GetConnStringName()); + return resolver.Resolve(typeof(T)); } [NotNull] public static Task ResolveAsync(this IConnectionStringResolver resolver) { - return resolver.ResolveAsync(ConnectionStringNameAttribute.GetConnStringName()); + return resolver.ResolveAsync(typeof(T)); + } + + [NotNull] + [Obsolete("Use ResolveAsync method")] + public static string Resolve(this IConnectionStringResolver resolver, Type type) + { + return resolver.Resolve(ConnectionStringNameAttribute.GetConnStringName(type)); + } + + [NotNull] + public static Task ResolveAsync(this IConnectionStringResolver resolver, Type type) + { + return resolver.ResolveAsync(ConnectionStringNameAttribute.GetConnStringName(type)); } } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IHasConcurrencyStamp.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Domain/Entities/IHasConcurrencyStamp.cs similarity index 100% rename from framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IHasConcurrencyStamp.cs rename to framework/src/Volo.Abp.Data/Volo/Abp/Domain/Entities/IHasConcurrencyStamp.cs diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/fi.json b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/fi.json new file mode 100644 index 0000000000..b6e404ec87 --- /dev/null +++ b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/fi.json @@ -0,0 +1,6 @@ +{ + "culture": "fi", + "texts": { + "MaxResultCountExceededExceptionMessage": "{0} voi olla enintään {1}! Lisää palvelimen puolella {2}. {3}, jotta saat enemmän tuloksia." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/hi.json b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/hi.json new file mode 100644 index 0000000000..d5189da8e5 --- /dev/null +++ b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/hi.json @@ -0,0 +1,6 @@ +{ + "culture": "hi", + "texts": { + "MaxResultCountExceededExceptionMessage": "{0} {1} से अधिक नहीं हो सकता! अधिक परिणाम की अनुमति देने के लिए सर्वर पक्ष पर {2}। {3} बढ़ाएँ।" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/it.json b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/it.json new file mode 100644 index 0000000000..1661d0624f --- /dev/null +++ b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/it.json @@ -0,0 +1,6 @@ +{ + "culture": "it", + "texts": { + "MaxResultCountExceededExceptionMessage": "{0} non può essere maggiore di {1}! Aumenta {2}. {3} sul lato server per consentire più risultati." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs index 922b887bfa..821bff2ef3 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Volo.Abp.Aspects; using Volo.Abp.Auditing; using Volo.Abp.Authorization; +using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; @@ -59,6 +60,8 @@ namespace Volo.Abp.Application.Services protected ILoggerFactory LoggerFactory => LazyServiceProvider.LazyGetRequiredService(); protected ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService(); + + protected IDataFilter DataFilter => LazyServiceProvider.LazyGetRequiredService(); protected ICurrentUser CurrentUser => LazyServiceProvider.LazyGetRequiredService(); diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs index 6408e3f0fa..ee172b3409 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs @@ -55,7 +55,7 @@ namespace Volo.Abp.DependencyInjection throw new AbpException($"{OriginalDbContextType.AssemblyQualifiedName} should inherit/implement {otherDbContextType.AssemblyQualifiedName}!"); } - ReplacedDbContextTypes.Add(otherDbContextType); + ReplacedDbContextTypes.AddIfNotContains(otherDbContextType); return this; } @@ -93,9 +93,9 @@ namespace Volo.Abp.DependencyInjection public IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepository(Type entityType) { EntityHelper.CheckEntity(entityType); - + SpecifiedDefaultRepositories.AddIfNotContains(entityType); - + return this; } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs new file mode 100644 index 0000000000..625e6841a0 --- /dev/null +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace Volo.Abp.DependencyInjection +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public class ReplaceDbContextAttribute : Attribute + { + public Type[] ReplacedDbContextTypes { get; } + + public ReplaceDbContextAttribute(params Type[] replacedDbContextTypes) + { + ReplacedDbContextTypes = replacedDbContextTypes; + } + } +} diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/fi.json b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/fi.json new file mode 100644 index 0000000000..ac197f1634 --- /dev/null +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/fi.json @@ -0,0 +1,25 @@ +{ + "culture": "fi", + "texts": { + "DisplayName:Abp.Mailing.DefaultFromAddress": "Oletus osoitteesta", + "DisplayName:Abp.Mailing.DefaultFromDisplayName": "Oletus näyttönimestä", + "DisplayName:Abp.Mailing.Smtp.Host": "Isäntä", + "DisplayName:Abp.Mailing.Smtp.Port": "Satama", + "DisplayName:Abp.Mailing.Smtp.UserName": "Käyttäjänimi", + "DisplayName:Abp.Mailing.Smtp.Password": "Salasana", + "DisplayName:Abp.Mailing.Smtp.Domain": "Verkkotunnus", + "DisplayName:Abp.Mailing.Smtp.EnableSsl": "Ota SSL käyttöön", + "DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "Käytä oletusarvoisia tunnistetietoja", + "Description:Abp.Mailing.DefaultFromAddress": "Oletus osoitteesta", + "Description:Abp.Mailing.DefaultFromDisplayName": "Oletusnimi näyttönimestä", + "Description:Abp.Mailing.Smtp.Host": "SMTP-tapahtumiin käytetyn isännän nimi tai IP-osoite.", + "Description:Abp.Mailing.Smtp.Port": "SMTP-tapahtumiin käytetty portti.", + "Description:Abp.Mailing.Smtp.UserName": "Käyttäjätunnuksiin liittyvä käyttäjänimi.", + "Description:Abp.Mailing.Smtp.Password": "Tunnistetietoihin liittyvän käyttäjänimen salasana.", + "Description:Abp.Mailing.Smtp.Domain": "Verkkotunnus tai tietokoneen nimi, joka tarkistaa tunnistetiedot.", + "Description:Abp.Mailing.Smtp.EnableSsl": "Käyttääkö SmtpClient Secure Sockets Layer (SSL) -yhteyttä yhteyden salaamiseen.", + "Description:Abp.Mailing.Smtp.UseDefaultCredentials": "Lähetetäänkö DefaultCredentials pyyntöjen kanssa.", + "TextTemplate:StandardEmailTemplates.Layout": "Oletussähköpostiasettelumalli", + "TextTemplate:StandardEmailTemplates.Message": "Yksinkertainen viestimalli sähköpostiviesteille" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/hi.json b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/hi.json new file mode 100644 index 0000000000..4b69d8588d --- /dev/null +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/hi.json @@ -0,0 +1,25 @@ +{ + "culture": "hi", + "texts": { + "DisplayName:Abp.Mailing.DefaultFromAddress": "पते से डिफ़ॉल्ट", + "DisplayName:Abp.Mailing.DefaultFromDisplayName": "प्रदर्शन नाम से डिफ़ॉल्ट", + "DisplayName:Abp.Mailing.Smtp.Host": "मेज़बान", + "DisplayName:Abp.Mailing.Smtp.Port": "बंदरगाह", + "DisplayName:Abp.Mailing.Smtp.UserName": "उपयोगकर्ता नाम", + "DisplayName:Abp.Mailing.Smtp.Password": "कुंजिका", + "DisplayName:Abp.Mailing.Smtp.Domain": "डोमेन", + "DisplayName:Abp.Mailing.Smtp.EnableSsl": "SSL सक्षम करें", + "DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "डिफ़ॉल्ट क्रेडेंशियल्स का उपयोग करें", + "Description:Abp.Mailing.DefaultFromAddress": "पते से डिफ़ॉल्ट", + "Description:Abp.Mailing.DefaultFromDisplayName": "प्रदर्शन नाम से डिफ़ॉल्ट", + "Description:Abp.Mailing.Smtp.Host": "SMTP लेनदेन के लिए उपयोग किए गए होस्ट का नाम या IP पता।", + "Description:Abp.Mailing.Smtp.Port": "SMTP लेनदेन के लिए उपयोग किया जाने वाला पोर्ट।", + "Description:Abp.Mailing.Smtp.UserName": "उपयोगकर्ता नाम क्रेडेंशियल्स के साथ जुड़ा हुआ है।", + "Description:Abp.Mailing.Smtp.Password": "क्रेडेंशियल्स के साथ जुड़े उपयोगकर्ता नाम का पासवर्ड।", + "Description:Abp.Mailing.Smtp.Domain": "डोमेन या कंप्यूटर का नाम जो क्रेडेंशियल्स को सत्यापित करता है।", + "Description:Abp.Mailing.Smtp.EnableSsl": "क्या SmtpClient कनेक्शन को एन्क्रिप्ट करने के लिए सिक्योर सॉकेट्स लेयर (एसएसएल) का उपयोग करता है।", + "Description:Abp.Mailing.Smtp.UseDefaultCredentials": "क्या DefaultCredentials अनुरोधों के साथ भेजे जाते हैं।", + "TextTemplate:StandardEmailTemplates.Layout": "डिफ़ॉल्ट ईमेल लेआउट टेम्पलेट", + "TextTemplate:StandardEmailTemplates.Message": "ईमेल के लिए सरल संदेश टेम्पलेट" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/it.json b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/it.json new file mode 100644 index 0000000000..34b5f573c5 --- /dev/null +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/it.json @@ -0,0 +1,25 @@ +{ + "culture": "it", + "texts": { + "DisplayName:Abp.Mailing.DefaultFromAddress": "Indirizzo predefinito dall'indirizzo", + "DisplayName:Abp.Mailing.DefaultFromDisplayName": "Predefinito dal nome visualizzato", + "DisplayName:Abp.Mailing.Smtp.Host": "Ospite", + "DisplayName:Abp.Mailing.Smtp.Port": "Porta", + "DisplayName:Abp.Mailing.Smtp.UserName": "Nome utente", + "DisplayName:Abp.Mailing.Smtp.Password": "Parola d'ordine", + "DisplayName:Abp.Mailing.Smtp.Domain": "Dominio", + "DisplayName:Abp.Mailing.Smtp.EnableSsl": "Abilita SSL", + "DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "Usa credenziali predefinite", + "Description:Abp.Mailing.DefaultFromAddress": "L'indirizzo predefinito da", + "Description:Abp.Mailing.DefaultFromDisplayName": "Il valore predefinito dal nome visualizzato", + "Description:Abp.Mailing.Smtp.Host": "Il nome o l'indirizzo IP dell'host utilizzato per le transazioni SMTP.", + "Description:Abp.Mailing.Smtp.Port": "La porta utilizzata per le transazioni SMTP.", + "Description:Abp.Mailing.Smtp.UserName": "Nome utente associato alle credenziali.", + "Description:Abp.Mailing.Smtp.Password": "La password per il nome utente associato alle credenziali.", + "Description:Abp.Mailing.Smtp.Domain": "Il nome di dominio o computer che verifica le credenziali.", + "Description:Abp.Mailing.Smtp.EnableSsl": "Se SmtpClient utilizza SSL (Secure Sockets Layer) per crittografare la connessione.", + "Description:Abp.Mailing.Smtp.UseDefaultCredentials": "Indica se DefaultCredentials vengono inviati con richieste.", + "TextTemplate:StandardEmailTemplates.Layout": "Modello di layout di posta elettronica predefinito", + "TextTemplate:StandardEmailTemplates.Message": "Modello di messaggio semplice per e-mail" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo.Abp.EntityFrameworkCore.MySQL.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo.Abp.EntityFrameworkCore.MySQL.csproj index 87fd075166..95b5158562 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo.Abp.EntityFrameworkCore.MySQL.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo.Abp.EntityFrameworkCore.MySQL.csproj @@ -19,7 +19,7 @@ - + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj index 8c1f0cdec3..900a84eca6 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj @@ -19,7 +19,7 @@ - + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs index 538614ee22..a48575ddcc 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs @@ -1,5 +1,8 @@ using System; +using System.Linq; +using System.Reflection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.DependencyInjection; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.DependencyInjection; @@ -8,13 +11,22 @@ namespace Microsoft.Extensions.DependencyInjection public static class AbpEfCoreServiceCollectionExtensions { public static IServiceCollection AddAbpDbContext( - this IServiceCollection services, + this IServiceCollection services, Action optionsBuilder = null) where TDbContext : AbpDbContext { services.AddMemoryCache(); var options = new AbpDbContextRegistrationOptions(typeof(TDbContext), services); + + var replacedDbContextTypes = typeof(TDbContext).GetCustomAttributes(true) + .SelectMany( x => x.ReplacedDbContextTypes).ToList(); + + foreach (var dbContextType in replacedDbContextTypes) + { + options.ReplaceDbContext(dbContextType); + } + optionsBuilder?.Invoke(options); services.TryAddTransient(DbContextOptionsFactory.Create); diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs index 92c6935900..75dd6a5dc4 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs @@ -39,6 +39,11 @@ namespace Volo.Abp.EntityFrameworkCore DefaultConfigureAction = action; } + public bool IsConfiguredDefault() + { + return DefaultConfigureAction != null; + } + public void PreConfigure([NotNull] Action> action) where TDbContext : AbpDbContext { @@ -60,6 +65,16 @@ namespace Volo.Abp.EntityFrameworkCore ConfigureActions[typeof(TDbContext)] = action; } + + public bool IsConfigured() + { + return IsConfigured(typeof(TDbContext)); + } + + public bool IsConfigured(Type dbContextType) + { + return ConfigureActions.ContainsKey(dbContextType); + } internal Type GetReplacedTypeOrSelf(Type dbContextType) { diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs index e92c8d35fa..b5d9eb8436 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs @@ -1,6 +1,8 @@ using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Domain; +using Volo.Abp.EntityFrameworkCore.DependencyInjection; using Volo.Abp.Modularity; using Volo.Abp.Uow.EntityFrameworkCore; diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs index 2fa56b550b..e5e4c2584a 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/UnitOfWorkDbContextProvider.cs @@ -62,10 +62,9 @@ namespace Volo.Abp.Uow.EntityFrameworkCore throw new AbpException("A DbContext can only be created inside a unit of work!"); } - var connectionStringName = ConnectionStringNameAttribute.GetConnStringName(); - var connectionString = ResolveConnectionString(connectionStringName); - var targetDbContextType = _options.GetReplacedTypeOrSelf(typeof(TDbContext)); + var connectionStringName = ConnectionStringNameAttribute.GetConnStringName(targetDbContextType); + var connectionString = ResolveConnectionString(connectionStringName); var dbContextKey = $"{targetDbContextType.FullName}_{connectionString}"; var databaseApi = unitOfWork.GetOrAddDatabaseApi( @@ -85,10 +84,10 @@ namespace Volo.Abp.Uow.EntityFrameworkCore throw new AbpException("A DbContext can only be created inside a unit of work!"); } - var connectionStringName = ConnectionStringNameAttribute.GetConnStringName(); + var targetDbContextType = _options.GetReplacedTypeOrSelf(typeof(TDbContext)); + var connectionStringName = ConnectionStringNameAttribute.GetConnStringName(targetDbContextType); var connectionString = await ResolveConnectionStringAsync(connectionStringName); - var targetDbContextType = _options.GetReplacedTypeOrSelf(typeof(TDbContext)); var dbContextKey = $"{targetDbContextType.FullName}_{connectionString}"; var databaseApi = unitOfWork.FindDatabaseApi(dbContextKey); diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fi.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fi.json new file mode 100644 index 0000000000..03f1ce3b5c --- /dev/null +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fi.json @@ -0,0 +1,25 @@ +{ + "culture": "fi", + "texts": { + "InternalServerErrorMessage": "Pyynnön aikana tapahtui sisäinen virhe!", + "ValidationErrorMessage": "Pyyntösi ei kelpaa!", + "ValidationNarrativeErrorMessageTitle": "Seuraavat virheet havaittiin validoinnin aikana.", + "DefaultErrorMessage": "Tapahtui virhe!", + "DefaultErrorMessageDetail": "Palvelin ei lähettänyt virhetietoja.", + "DefaultErrorMessage401": "Sinua ei ole todennettu!", + "DefaultErrorMessage401Detail": "Suorita tämä toimenpide kirjautumalla sisään.", + "DefaultErrorMessage403": "Sinulla ei ole valtuuksia!", + "DefaultErrorMessage403Detail": "Et saa suorittaa tätä toimintoa!", + "DefaultErrorMessage404": "Resurssia ei löydy!", + "DefaultErrorMessage404Detail": "Pyydettyä resurssia ei löytynyt palvelimelta!", + "EntityNotFoundErrorMessage": "Ei ole olemassa kohdetta {0}, jonka tunnus = {1}!", + "Error": "Virhe", + "UnhandledException": "Käsittelemätön poikkeus!", + "401Message": "Luvaton", + "403Message": "Kielletty", + "404Message": "Sivua ei löydetty", + "500Message": "Sisäinen palvelinvirhe", + "403MessageDetail": "Sinulla ei ole oikeutta suorittaa tätä toimintoa!", + "404MessageDetail": "Valitettavasti tässä osoitteessa ei ole mitään." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fr.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fr.json index f1c9713e65..cdbd620313 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fr.json +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/fr.json @@ -18,6 +18,8 @@ "401Message": "Non autorisé", "403Message": "Interdit", "404Message": "Page introuvable", - "500Message": "Erreur Interne du Serveur" + "500Message": "Erreur Interne du Serveur", + "403MessageDetail": "Vous n'êtes pas autorisé à effectuer cette opération!", + "404MessageDetail": "Désolé, il n'y a rien à cette adresse." } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hi.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hi.json new file mode 100644 index 0000000000..47c8cdda55 --- /dev/null +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/hi.json @@ -0,0 +1,25 @@ +{ + "culture": "hi", + "texts": { + "InternalServerErrorMessage": "आपके अनुरोध के दौरान एक आंतरिक त्रुटि हुई!", + "ValidationErrorMessage": "आपका अनुरोध मान्य नहीं है!", + "ValidationNarrativeErrorMessageTitle": "सत्यापन के दौरान निम्नलिखित त्रुटियों का पता चला था।", + "DefaultErrorMessage": "एक गलती हुई है!", + "DefaultErrorMessageDetail": "सर्वर द्वारा त्रुटि विवरण नहीं भेजा गया।", + "DefaultErrorMessage401": "आप प्रमाणित नहीं हैं!", + "DefaultErrorMessage401Detail": "आपको यह ऑपरेशन करने के लिए साइन इन करना चाहिए।", + "DefaultErrorMessage403": "तुम अधिकृत नहीं हो!", + "DefaultErrorMessage403Detail": "आपको यह ऑपरेशन करने की अनुमति नहीं है!", + "DefaultErrorMessage404": "संसाधन नही मिला!", + "DefaultErrorMessage404Detail": "अनुरोधित संसाधन सर्वर पर नहीं मिला!", + "EntityNotFoundErrorMessage": "Id = {1} के साथ कोई इकाई {0} नहीं है!", + "Error": "त्रुटि", + "UnhandledException": "अनियंत्रित अपवाद!", + "401Message": "अनधिकृत", + "403Message": "मना किया हुआ", + "404Message": "पृष्ठ नहीं मिला", + "500Message": "आंतरिक सर्वर त्रुटि", + "403MessageDetail": "आप इस ऑपरेशन को करने के लिए अधिकृत नहीं हैं!", + "404MessageDetail": "क्षमा करें, इस पते पर कुछ भी नहीं है।" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/it.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/it.json new file mode 100644 index 0000000000..b2025559fe --- /dev/null +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/it.json @@ -0,0 +1,25 @@ +{ + "culture": "it", + "texts": { + "InternalServerErrorMessage": "Si è verificato un errore interno durante la tua richiesta!", + "ValidationErrorMessage": "La tua richiesta non è valida!", + "ValidationNarrativeErrorMessageTitle": "Durante la convalida sono stati rilevati i seguenti errori.", + "DefaultErrorMessage": "C'è stato un errore!", + "DefaultErrorMessageDetail": "Dettaglio errore non inviato dal server.", + "DefaultErrorMessage401": "Non sei autenticato!", + "DefaultErrorMessage401Detail": "È necessario accedere per eseguire questa operazione.", + "DefaultErrorMessage403": "Non sei autorizzato!", + "DefaultErrorMessage403Detail": "Non sei autorizzato a eseguire questa operazione!", + "DefaultErrorMessage404": "Risorsa non trovata!", + "DefaultErrorMessage404Detail": "La risorsa richiesta non è stata trovata sul server!", + "EntityNotFoundErrorMessage": "Non esiste un'entità {0} con id = {1}!", + "Error": "Errore", + "UnhandledException": "Eccezione non gestita!", + "401Message": "Non autorizzato", + "403Message": "Vietato", + "404Message": "pagina non trovata", + "500Message": "Errore interno del server", + "403MessageDetail": "Non sei autorizzato a eseguire questa operazione!", + "404MessageDetail": "Spiacenti, non c'è niente a questo indirizzo." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureSimpleStateCheckerExtensions.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureSimpleStateCheckerExtensions.cs new file mode 100644 index 0000000000..d06e55effa --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/FeatureSimpleStateCheckerExtensions.cs @@ -0,0 +1,30 @@ +using JetBrains.Annotations; +using Volo.Abp.SimpleStateChecking; + +namespace Volo.Abp.Features +{ + public static class FeatureSimpleStateCheckerExtensions + { + public static TState RequireFeatures( + [NotNull] this TState state, + params string[] features) + where TState : IHasSimpleStateCheckers + { + state.RequireFeatures(true, features); + return state; + } + + public static TState RequireFeatures( + [NotNull] this TState state, + bool requiresAll, + params string[] features) + where TState : IHasSimpleStateCheckers + { + Check.NotNull(state, nameof(state)); + Check.NotNullOrEmpty(features, nameof(features)); + + state.StateCheckers.Add(new RequireFeaturesSimpleStateChecker(requiresAll, features)); + return state; + } + } +} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/FR.json b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/FR.json new file mode 100644 index 0000000000..19fb314868 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/FR.json @@ -0,0 +1,8 @@ +{ + "culture": "fr", + "texts": { + "Volo.Feature:010001": "La fonctionnalité n'est pas activée: {FeatureName}", + "Volo.Feature:010002": "Les fonctionnalités requises ne sont pas activées. Toutes ces fonctionnalités doivent être activées: {FeatureNames}", + "Volo.Feature:010003": "Les fonctionnalités requises ne sont pas activées. Au moins une de ces fonctionnalités doit être activée: {FeatureNames}" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/fi.json b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/fi.json new file mode 100644 index 0000000000..4bc400d6f9 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/fi.json @@ -0,0 +1,8 @@ +{ + "culture": "fi", + "texts": { + "Volo.Feature:010001": "Ominaisuus ei ole käytössä: {FeatureName}", + "Volo.Feature:010002": "Vaaditut ominaisuudet eivät ole käytössä. Kaikkien näiden ominaisuuksien on oltava käytössä: {FeatureNames}", + "Volo.Feature:010003": "Vaaditut ominaisuudet eivät ole käytössä. Ainakin yhden näistä ominaisuuksista on oltava käytössä: {FeatureNames}" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/hi.json b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/hi.json new file mode 100644 index 0000000000..6137a0417c --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/hi.json @@ -0,0 +1,8 @@ +{ + "culture": "hi", + "texts": { + "Volo.Feature:010001": "फ़ीचर सक्षम नहीं है: {FeatureName}", + "Volo.Feature:010002": "आवश्यक सुविधाएँ सक्षम नहीं हैं। ये सभी सुविधाएँ सक्षम होनी चाहिए: {FeatureNames}", + "Volo.Feature:010003": "आवश्यक सुविधाएँ सक्षम नहीं हैं। इन विशेषताओं में से कम से कम एक सक्षम होना चाहिए: {FeatureNames}" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/it.json b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/it.json new file mode 100644 index 0000000000..0991d78716 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/it.json @@ -0,0 +1,8 @@ +{ + "culture": "it", + "texts": { + "Volo.Feature:010001": "La funzione non è abilitata: {FeatureName}", + "Volo.Feature:010002": "Le funzionalità richieste non sono abilitate. Tutte queste funzioni devono essere abilitate: {FeatureNames}", + "Volo.Feature:010003": "Le funzionalità richieste non sono abilitate. Almeno una di queste funzioni deve essere abilitata: {FeatureNames}" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/PermissionDefinitionExtensions.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/PermissionDefinitionExtensions.cs deleted file mode 100644 index a213232f2f..0000000000 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/PermissionDefinitionExtensions.cs +++ /dev/null @@ -1,28 +0,0 @@ -using JetBrains.Annotations; -using Volo.Abp.Authorization.Permissions; - -namespace Volo.Abp.Features -{ - public static class FeatureDefinitionExtensions - { - public static PermissionDefinition RequireFeatures( - [NotNull] this PermissionDefinition permissionDefinition, - params string[] features) - { - return permissionDefinition.RequireFeatures(true, features); - } - - public static PermissionDefinition RequireFeatures( - [NotNull] this PermissionDefinition permissionDefinition, - bool requiresAll, - params string[] features) - { - Check.NotNull(permissionDefinition, nameof(permissionDefinition)); - Check.NotNullOrEmpty(features, nameof(features)); - - return permissionDefinition.AddStateProviders( - new RequireFeaturesPermissionStateProvider(requiresAll, features) - ); - } - } -} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/RequireFeaturesPermissionStateProvider.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/RequireFeaturesPermissionStateProvider.cs deleted file mode 100644 index 0fee54c598..0000000000 --- a/framework/src/Volo.Abp.Features/Volo/Abp/Features/RequireFeaturesPermissionStateProvider.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Authorization.Permissions; - -namespace Volo.Abp.Features -{ - public class RequireFeaturesPermissionStateProvider : IPermissionStateProvider - { - private readonly string[] _featureNames; - private readonly bool _requiresAll; - - public RequireFeaturesPermissionStateProvider(params string[] featureNames) - : this(true, featureNames) - { - - } - - public RequireFeaturesPermissionStateProvider(bool requiresAll, params string[] featureNames) - { - Check.NotNullOrEmpty(featureNames, nameof(featureNames)); - - _requiresAll = requiresAll; - _featureNames = featureNames; - } - - public async Task IsEnabledAsync(PermissionStateContext context) - { - var feature = context.ServiceProvider.GetRequiredService(); - return await feature.IsEnabledAsync(_requiresAll, _featureNames); - } - } -} diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/RequireFeaturesSimpleStateChecker.cs b/framework/src/Volo.Abp.Features/Volo/Abp/Features/RequireFeaturesSimpleStateChecker.cs new file mode 100644 index 0000000000..1a4c028653 --- /dev/null +++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/RequireFeaturesSimpleStateChecker.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.SimpleStateChecking; + +namespace Volo.Abp.Features +{ + public class RequireFeaturesSimpleStateChecker : ISimpleStateChecker + where TState : IHasSimpleStateCheckers + { + private readonly string[] _featureNames; + private readonly bool _requiresAll; + + public RequireFeaturesSimpleStateChecker(params string[] featureNames) + : this(true, featureNames) + { + } + + public RequireFeaturesSimpleStateChecker(bool requiresAll, params string[] featureNames) + { + Check.NotNullOrEmpty(featureNames, nameof(featureNames)); + + _requiresAll = requiresAll; + _featureNames = featureNames; + } + + public async Task IsEnabledAsync(SimpleStateCheckerContext context) + { + var featureChecker = context.ServiceProvider.GetRequiredService(); + return await featureChecker.IsEnabledAsync(_requiresAll, _featureNames); + } + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo.Abp.GlobalFeatures.csproj b/framework/src/Volo.Abp.GlobalFeatures/Volo.Abp.GlobalFeatures.csproj index 456366b542..024ec5ec17 100644 --- a/framework/src/Volo.Abp.GlobalFeatures/Volo.Abp.GlobalFeatures.csproj +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo.Abp.GlobalFeatures.csproj @@ -20,7 +20,6 @@ - diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureDefinitionExtensions.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureDefinitionExtensions.cs deleted file mode 100644 index 299994e695..0000000000 --- a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureDefinitionExtensions.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using JetBrains.Annotations; -using Volo.Abp.Authorization.Permissions; - -namespace Volo.Abp.GlobalFeatures -{ - public static class GlobalFeatureDefinitionExtensions - { - public static PermissionDefinition RequireGlobalFeatures( - this PermissionDefinition permissionDefinition, - params string[] globalFeatures) - { - return permissionDefinition.RequireGlobalFeatures(true, globalFeatures); - } - - public static PermissionDefinition RequireGlobalFeatures( - [NotNull] this PermissionDefinition permissionDefinition, - bool requiresAll, - params string[] globalFeatures) - { - Check.NotNull(permissionDefinition, nameof(permissionDefinition)); - Check.NotNullOrEmpty(globalFeatures, nameof(globalFeatures)); - - return permissionDefinition.AddStateProviders( - new RequireGlobalFeaturesPermissionStateProvider(requiresAll, globalFeatures) - ); - } - - public static PermissionDefinition RequireGlobalFeatures( - this PermissionDefinition permissionDefinition, - params Type[] globalFeatures) - { - return permissionDefinition.RequireGlobalFeatures(true, globalFeatures); - } - - public static PermissionDefinition RequireGlobalFeatures( - [NotNull] this PermissionDefinition permissionDefinition, - bool requiresAll, - params Type[] globalFeatures) - { - Check.NotNull(permissionDefinition, nameof(permissionDefinition)); - Check.NotNullOrEmpty(globalFeatures, nameof(globalFeatures)); - - return permissionDefinition.AddStateProviders( - new RequireGlobalFeaturesPermissionStateProvider(requiresAll, globalFeatures) - ); - } - - } -} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureSimpleStateCheckerExtensions.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureSimpleStateCheckerExtensions.cs new file mode 100644 index 0000000000..f18f3d1569 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/GlobalFeatureSimpleStateCheckerExtensions.cs @@ -0,0 +1,51 @@ +using System; +using JetBrains.Annotations; +using Volo.Abp.SimpleStateChecking; + +namespace Volo.Abp.GlobalFeatures +{ + public static class GlobalFeatureSimpleStateCheckerExtensions + { + public static TState RequireGlobalFeatures( + [NotNull] this TState state, + params string[] globalFeatures) + where TState : IHasSimpleStateCheckers + { + return state.RequireGlobalFeatures(true, globalFeatures); + } + + public static TState RequireGlobalFeatures( + [NotNull] this TState state, + bool requiresAll, + params string[] globalFeatures) + where TState : IHasSimpleStateCheckers + { + Check.NotNull(state, nameof(state)); + Check.NotNullOrEmpty(globalFeatures, nameof(globalFeatures)); + + state.StateCheckers.Add(new RequireGlobalFeaturesSimpleStateChecker(requiresAll, globalFeatures)); + return state; + } + + public static TState RequireGlobalFeatures( + [NotNull] this TState state, + params Type[] globalFeatures) + where TState : IHasSimpleStateCheckers + { + return state.RequireGlobalFeatures(true, globalFeatures); + } + + public static TState RequireGlobalFeatures( + [NotNull] this TState state, + bool requiresAll, + params Type[] globalFeatures) + where TState : IHasSimpleStateCheckers + { + Check.NotNull(state, nameof(state)); + Check.NotNullOrEmpty(globalFeatures, nameof(globalFeatures)); + + state.StateCheckers.Add(new RequireGlobalFeaturesSimpleStateChecker(requiresAll, globalFeatures)); + return state; + } + } +} diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/FR.json b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/FR.json new file mode 100644 index 0000000000..8062337807 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/FR.json @@ -0,0 +1,6 @@ +{ + "culture": "fr", + "texts": { + "Volo.GlobalFeature:010001": "Le service \"{ServiceName}\" doit activer la fonction \"{GlobalFeatureName}\"." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/fi.json b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/fi.json new file mode 100644 index 0000000000..b842a7e3a4 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/fi.json @@ -0,0 +1,6 @@ +{ + "culture": "fi", + "texts": { + "Volo.GlobalFeature:010001": "Palvelun {ServiceName} on oltava käytössä {GlobalFeatureName} -ominaisuus." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/hi.json b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/hi.json new file mode 100644 index 0000000000..ca41828fa1 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/hi.json @@ -0,0 +1,6 @@ +{ + "culture": "hi", + "texts": { + "Volo.GlobalFeature:010001": "'{ServiceName}' सेवा को '{GlobalFeatureName}' सुविधा को सक्षम करने की आवश्यकता है।" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/it.json b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/it.json new file mode 100644 index 0000000000..21ba5047da --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/it.json @@ -0,0 +1,6 @@ +{ + "culture": "it", + "texts": { + "Volo.GlobalFeature:010001": "Il servizio \"{ServiceName}\" deve abilitare la funzione \"{GlobalFeatureName}\"." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/nl.json b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/nl.json new file mode 100644 index 0000000000..449c09efd6 --- /dev/null +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/nl.json @@ -0,0 +1,6 @@ +{ + "culture": "nl", + "texts": { + "Volo.GlobalFeature:010001": "De service '{ServiceName}' moet de functie '{GlobalFeatureName}' inschakelen." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/RequireGlobalFeaturesPermissionStateProvider.cs b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/RequireGlobalFeaturesSimpleStateChecker.cs similarity index 61% rename from framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/RequireGlobalFeaturesPermissionStateProvider.cs rename to framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/RequireGlobalFeaturesSimpleStateChecker.cs index c96e652e8c..12754d87df 100644 --- a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/RequireGlobalFeaturesPermissionStateProvider.cs +++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/RequireGlobalFeaturesSimpleStateChecker.cs @@ -1,21 +1,22 @@ using System; using System.Linq; using System.Threading.Tasks; -using Volo.Abp.Authorization.Permissions; +using Volo.Abp.SimpleStateChecking; namespace Volo.Abp.GlobalFeatures { - public class RequireGlobalFeaturesPermissionStateProvider : IPermissionStateProvider + public class RequireGlobalFeaturesSimpleStateChecker : ISimpleStateChecker + where TState : IHasSimpleStateCheckers { private readonly string[] _globalFeatureNames; private readonly bool _requiresAll; - public RequireGlobalFeaturesPermissionStateProvider(params string[] globalFeatureNames) + public RequireGlobalFeaturesSimpleStateChecker(params string[] globalFeatureNames) : this(true, globalFeatureNames) { } - public RequireGlobalFeaturesPermissionStateProvider(bool requiresAll, params string[] globalFeatureNames) + public RequireGlobalFeaturesSimpleStateChecker(bool requiresAll, params string[] globalFeatureNames) { Check.NotNullOrEmpty(globalFeatureNames, nameof(globalFeatureNames)); @@ -23,7 +24,7 @@ namespace Volo.Abp.GlobalFeatures _globalFeatureNames = globalFeatureNames; } - public RequireGlobalFeaturesPermissionStateProvider(bool requiresAll, params Type[] globalFeatureNames) + public RequireGlobalFeaturesSimpleStateChecker(bool requiresAll, params Type[] globalFeatureNames) { Check.NotNullOrEmpty(globalFeatureNames, nameof(globalFeatureNames)); @@ -31,9 +32,9 @@ namespace Volo.Abp.GlobalFeatures _globalFeatureNames = globalFeatureNames.Select(GlobalFeatureNameAttribute.GetName).ToArray(); } - public Task IsEnabledAsync(PermissionStateContext context) + public Task IsEnabledAsync(SimpleStateCheckerContext context) { - bool isEnabled = _requiresAll + var isEnabled = _requiresAll ? _globalFeatureNames.All(x => GlobalFeatureManager.Instance.IsEnabled(x)) : _globalFeatureNames.Any(x => GlobalFeatureManager.Instance.IsEnabled(x)); diff --git a/framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator.cs b/framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator.cs index c86fc095c7..3f74918d98 100644 --- a/framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator.cs +++ b/framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator.cs @@ -1,6 +1,9 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using IdentityModel.Client; +using JetBrains.Annotations; using Microsoft.AspNetCore.Components.WebAssembly.Authentication; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; using Volo.Abp.Http.Client.Authentication; using Volo.Abp.IdentityModel; @@ -8,16 +11,18 @@ using Volo.Abp.IdentityModel; namespace Volo.Abp.Http.Client.IdentityModel.WebAssembly { [Dependency(ReplaceServices = true)] - public class AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator : IdentityModelRemoteServiceHttpClientAuthenticator + public class AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator + : IdentityModelRemoteServiceHttpClientAuthenticator { + [CanBeNull] protected IAccessTokenProvider AccessTokenProvider { get; } public AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator( IIdentityModelAuthenticationService identityModelAuthenticationService, - IAccessTokenProvider accessTokenProvider) + IServiceProvider serviceProvider) : base(identityModelAuthenticationService) { - AccessTokenProvider = accessTokenProvider; + AccessTokenProvider = serviceProvider.GetService(); } public override async Task Authenticate(RemoteServiceHttpClientAuthenticateContext context) @@ -37,6 +42,11 @@ namespace Volo.Abp.Http.Client.IdentityModel.WebAssembly protected virtual async Task GetAccessTokenFromAccessTokenProviderOrNullAsync() { + if (AccessTokenProvider == null) + { + return null; + } + var result = await AccessTokenProvider.RequestAccessToken(); if (result.Status != AccessTokenResultStatus.Success) { diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs index 5bee246bd0..4d77423c7f 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/UrlBuilder.cs @@ -15,12 +15,18 @@ namespace Volo.Abp.Http.Client.DynamicProxying { public static string GenerateUrlWithParameters(ActionApiDescriptionModel action, IReadOnlyDictionary methodArguments, ApiVersionInfo apiVersion) { - var urlBuilder = new StringBuilder(action.Url); + // The ASP.NET Core route value provider and query string value provider: + // Treat values as invariant culture. + // Expect that URLs are culture-invariant. + using (CultureHelper.Use(CultureInfo.InvariantCulture)) + { + var urlBuilder = new StringBuilder(action.Url); - ReplacePathVariables(urlBuilder, action.Parameters, methodArguments, apiVersion); - AddQueryStringParameters(urlBuilder, action.Parameters, methodArguments, apiVersion); + ReplacePathVariables(urlBuilder, action.Parameters, methodArguments, apiVersion); + AddQueryStringParameters(urlBuilder, action.Parameters, methodArguments, apiVersion); - return urlBuilder.ToString(); + return urlBuilder.ToString(); + } } private static void ReplacePathVariables(StringBuilder urlBuilder, IList actionParameters, IReadOnlyDictionary methodArguments, ApiVersionInfo apiVersion) @@ -128,15 +134,12 @@ namespace Volo.Abp.Http.Client.DynamicProxying private static string ConvertValueToString([NotNull] object value) { - using (CultureHelper.Use(CultureInfo.InvariantCulture)) + if (value is DateTime dateTimeValue) { - if (value is DateTime dateTimeValue) - { - return dateTimeValue.ToUniversalTime().ToString("u"); - } - - return value.ToString(); + return dateTimeValue.ToUniversalTime().ToString("O"); } + + return value.ToString(); } } } diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Generators/ProxyScriptingHelper.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Generators/ProxyScriptingHelper.cs index 700dc4e290..2568ccbb1c 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Generators/ProxyScriptingHelper.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Generators/ProxyScriptingHelper.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Volo.Abp.Http.Modeling; +using Volo.Abp.Localization; namespace Volo.Abp.Http.ProxyScripting.Generators { @@ -11,10 +13,16 @@ namespace Volo.Abp.Http.ProxyScripting.Generators public static string GenerateUrlWithParameters(ActionApiDescriptionModel action) { - //TODO: Can be optimized using StringBuilder? - var url = ReplacePathVariables(action.Url, action.Parameters); - url = AddQueryStringParameters(url, action.Parameters); - return url; + // The ASP.NET Core route value provider and query string value provider: + // Treat values as invariant culture. + // Expect that URLs are culture-invariant. + using (CultureHelper.Use(CultureInfo.InvariantCulture)) + { + //TODO: Can be optimized using StringBuilder? + var url = ReplacePathVariables(action.Url, action.Parameters); + url = AddQueryStringParameters(url, action.Parameters); + return url; + } } public static string GenerateHeaders(ActionApiDescriptionModel action, int indent = 0) diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/fi.json b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/fi.json new file mode 100644 index 0000000000..953f4491db --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/fi.json @@ -0,0 +1,15 @@ +{ + "culture": "fi", + "texts": { + "DisplayName:Abp.Ldap.ServerHost": "Palvelimen isäntä", + "Description:Abp.Ldap.ServerHost": "Palvelimen isäntä", + "DisplayName:Abp.Ldap.ServerPort": "Palvelimen portti", + "Description:Abp.Ldap.ServerPort": "Palvelimen portti", + "DisplayName:Abp.Ldap.BaseDc": "Perustoimialueen komponentti", + "Description:Abp.Ldap.BaseDc": "Perustoimialueen komponentti", + "DisplayName:Abp.Ldap.UserName": "Käyttäjätunnus", + "Description:Abp.Ldap.UserName": "Käyttäjätunnus", + "DisplayName:Abp.Ldap.Password": "Salasana", + "Description:Abp.Ldap.Password": "Salasana" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/hi.json b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/hi.json new file mode 100644 index 0000000000..b466bdb570 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/hi.json @@ -0,0 +1,15 @@ +{ + "culture": "hi", + "texts": { + "DisplayName:Abp.Ldap.ServerHost": "सर्वर होस्ट", + "Description:Abp.Ldap.ServerHost": "सर्वर होस्ट", + "DisplayName:Abp.Ldap.ServerPort": "सर्वर पोर्ट", + "Description:Abp.Ldap.ServerPort": "सर्वर पोर्ट", + "DisplayName:Abp.Ldap.BaseDc": "बेस डोमेन घटक", + "Description:Abp.Ldap.BaseDc": "बेस डोमेन घटक", + "DisplayName:Abp.Ldap.UserName": "उपयोगकर्ता नाम", + "Description:Abp.Ldap.UserName": "उपयोगकर्ता नाम", + "DisplayName:Abp.Ldap.Password": "कुंजिका", + "Description:Abp.Ldap.Password": "कुंजिका" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/it.json b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/it.json new file mode 100644 index 0000000000..61fd573b09 --- /dev/null +++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/it.json @@ -0,0 +1,15 @@ +{ + "culture": "it", + "texts": { + "DisplayName:Abp.Ldap.ServerHost": "Host del server", + "Description:Abp.Ldap.ServerHost": "Host del server", + "DisplayName:Abp.Ldap.ServerPort": "Porta del server", + "Description:Abp.Ldap.ServerPort": "Porta del server", + "DisplayName:Abp.Ldap.BaseDc": "Componente del dominio di base", + "Description:Abp.Ldap.BaseDc": "Componente del dominio di base", + "DisplayName:Abp.Ldap.UserName": "Nome utente", + "Description:Abp.Ldap.UserName": "Nome utente", + "DisplayName:Abp.Ldap.Password": "Parola d'ordine", + "Description:Abp.Ldap.Password": "Parola d'ordine" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/fi.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/fi.json new file mode 100644 index 0000000000..19b96532de --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/fi.json @@ -0,0 +1,7 @@ +{ + "culture": "fi", + "texts": { + "DisplayName:Abp.Localization.DefaultLanguage": "Oletuskieli", + "Description:Abp.Localization.DefaultLanguage": "Sovelluksen oletuskieli." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/hi.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/hi.json new file mode 100644 index 0000000000..fe3bb7f4ce --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/hi.json @@ -0,0 +1,7 @@ +{ + "culture": "hi", + "texts": { + "DisplayName:Abp.Localization.DefaultLanguage": "डिफ़ॉल्ट भाषा", + "Description:Abp.Localization.DefaultLanguage": "एप्लिकेशन की डिफ़ॉल्ट भाषा।" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/it.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/it.json new file mode 100644 index 0000000000..f42a817943 --- /dev/null +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/it.json @@ -0,0 +1,7 @@ +{ + "culture": "it", + "texts": { + "DisplayName:Abp.Localization.DefaultLanguage": "Lingua di default", + "Description:Abp.Localization.DefaultLanguage": "La lingua predefinita dell'applicazione." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs index c42036d1cd..5667d7de4d 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs @@ -22,17 +22,17 @@ namespace Volo.Abp.Localization.VirtualFiles _virtualPath = virtualPath; } - public void Initialize(LocalizationResourceInitializationContext context) + public virtual void Initialize(LocalizationResourceInitializationContext context) { _virtualFileProvider = context.ServiceProvider.GetRequiredService(); } - public LocalizedString GetOrNull(string cultureName, string name) + public virtual LocalizedString GetOrNull(string cultureName, string name) { return GetDictionaries().GetOrDefault(cultureName)?.GetOrNull(name); } - public void Fill(string cultureName, Dictionary dictionary) + public virtual void Fill(string cultureName, Dictionary dictionary) { GetDictionaries().GetOrDefault(cultureName)?.Fill(dictionary); } @@ -105,4 +105,4 @@ namespace Volo.Abp.Localization.VirtualFiles protected abstract ILocalizationDictionary CreateDictionaryFromFileContent(string fileContent); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs b/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs index 5adf7300ee..7f9c6b8d42 100644 --- a/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs @@ -1,5 +1,8 @@ using System; +using System.Linq; +using System.Reflection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.DependencyInjection; using Volo.Abp.MongoDB; using Volo.Abp.MongoDB.DependencyInjection; @@ -11,13 +14,22 @@ namespace Microsoft.Extensions.DependencyInjection where TMongoDbContext : AbpMongoDbContext { var options = new AbpMongoDbContextRegistrationOptions(typeof(TMongoDbContext), services); + + var replacedDbContextTypes = typeof(TMongoDbContext).GetCustomAttributes(true) + .SelectMany( x => x.ReplacedDbContextTypes).ToList(); + + foreach (var dbContextType in replacedDbContextTypes) + { + options.ReplaceDbContext(dbContextType); + } + optionsBuilder?.Invoke(options); foreach (var dbContextType in options.ReplacedDbContextTypes) { services.Replace(ServiceDescriptor.Transient(dbContextType, typeof(TMongoDbContext))); } - + foreach (var dbContextType in options.ReplacedDbContextTypes) { services.Replace( diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs index cb1ed7ea54..e0a6265f7c 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs @@ -1,5 +1,7 @@ using System; +using System.Reflection; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.DependencyInjection; namespace Volo.Abp.MongoDB.DependencyInjection diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs index a26307234d..2a3842441f 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs @@ -62,8 +62,8 @@ namespace Volo.Abp.Uow.MongoDB $"A {nameof(IMongoDatabase)} instance can only be created inside a unit of work!"); } - var connectionString = ResolveConnectionString(); var targetDbContextType = _options.GetReplacedTypeOrSelf(typeof(TMongoDbContext)); + var connectionString = ResolveConnectionString(targetDbContextType); var dbContextKey = $"{targetDbContextType.FullName}_{connectionString}"; var mongoUrl = new MongoUrl(connectionString); @@ -90,8 +90,8 @@ namespace Volo.Abp.Uow.MongoDB $"A {nameof(IMongoDatabase)} instance can only be created inside a unit of work!"); } - var connectionString = await ResolveConnectionStringAsync(); var targetDbContextType = _options.GetReplacedTypeOrSelf(typeof(TMongoDbContext)); + var connectionString = await ResolveConnectionStringAsync(targetDbContextType); var dbContextKey = $"{targetDbContextType.FullName}_{connectionString}"; var mongoUrl = new MongoUrl(connectionString); @@ -244,33 +244,33 @@ namespace Volo.Abp.Uow.MongoDB return dbContext; } - private async Task ResolveConnectionStringAsync() + private async Task ResolveConnectionStringAsync(Type dbContextType) { // Multi-tenancy unaware contexts should always use the host connection string if (typeof(TMongoDbContext).IsDefined(typeof(IgnoreMultiTenancyAttribute), false)) { using (_currentTenant.Change(null)) { - return await _connectionStringResolver.ResolveAsync(); + return await _connectionStringResolver.ResolveAsync(dbContextType); } } - return await _connectionStringResolver.ResolveAsync(); + return await _connectionStringResolver.ResolveAsync(dbContextType); } [Obsolete("Use ResolveConnectionStringAsync method.")] - private string ResolveConnectionString() + private string ResolveConnectionString(Type dbContextType) { // Multi-tenancy unaware contexts should always use the host connection string if (typeof(TMongoDbContext).IsDefined(typeof(IgnoreMultiTenancyAttribute), false)) { using (_currentTenant.Change(null)) { - return _connectionStringResolver.Resolve(); + return _connectionStringResolver.Resolve(dbContextType); } } - return _connectionStringResolver.Resolve(); + return _connectionStringResolver.Resolve(dbContextType); } protected virtual CancellationToken GetCancellationToken(CancellationToken preferredValue = default) diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfiguration.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfiguration.cs index e586e687c3..35b3a0e52e 100644 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfiguration.cs +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfiguration.cs @@ -13,12 +13,15 @@ namespace Volo.Abp.MultiTenancy public ConnectionStrings ConnectionStrings { get; set; } + public bool IsActive { get; set; } + public TenantConfiguration() { - + IsActive = true; } public TenantConfiguration(Guid id, [NotNull] string name) + : this() { Check.NotNull(name, nameof(name)); diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs index 81a9c72042..1c3223828d 100644 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantConfigurationProvider.cs @@ -42,6 +42,15 @@ namespace Volo.Abp.MultiTenancy details: "There is no tenant with the tenant id or name: " + resolveResult.TenantIdOrName ); } + + if (!tenant.IsActive) + { + throw new BusinessException( + code: "Volo.AbpIo.MultiTenancy:010002", + message: "Tenant not active!", + details: "The tenant is no active with the tenant id or name: " + resolveResult.TenantIdOrName + ); + } } return tenant; diff --git a/framework/src/Volo.Abp.Swashbuckle/Volo.Abp.Swashbuckle.csproj b/framework/src/Volo.Abp.Swashbuckle/Volo.Abp.Swashbuckle.csproj index c7fa0a1d11..0fa70fb6dd 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Volo.Abp.Swashbuckle.csproj +++ b/framework/src/Volo.Abp.Swashbuckle/Volo.Abp.Swashbuckle.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.TextTemplating.Core/FodyWeavers.xml b/framework/src/Volo.Abp.TextTemplating.Core/FodyWeavers.xml new file mode 100644 index 0000000000..be0de3a908 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.TextTemplating.Core/FodyWeavers.xsd b/framework/src/Volo.Abp.TextTemplating.Core/FodyWeavers.xsd new file mode 100644 index 0000000000..3f3946e282 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo.Abp.TextTemplating.Core.csproj b/framework/src/Volo.Abp.TextTemplating.Core/Volo.Abp.TextTemplating.Core.csproj new file mode 100644 index 0000000000..649bdc2912 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo.Abp.TextTemplating.Core.csproj @@ -0,0 +1,16 @@ + + + + + + + netstandard2.0 + + + + + + + + + diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTemplateRenderer.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTemplateRenderer.cs new file mode 100644 index 0000000000..4157910320 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTemplateRenderer.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.TextTemplating +{ + public class AbpTemplateRenderer : ITemplateRenderer, ITransientDependency + { + protected IServiceScopeFactory ServiceScopeFactory { get; } + protected ITemplateDefinitionManager TemplateDefinitionManager { get; } + protected AbpTextTemplatingOptions Options { get; } + + public AbpTemplateRenderer( + IServiceScopeFactory serviceScopeFactory, + ITemplateDefinitionManager templateDefinitionManager, + IOptions options) + { + ServiceScopeFactory = serviceScopeFactory; + TemplateDefinitionManager = templateDefinitionManager; + Options = options.Value; + } + + public virtual async Task RenderAsync( + string templateName, + object model = null, + string cultureName = null, + Dictionary globalContext = null) + { + var templateDefinition = TemplateDefinitionManager.Get(templateName); + + var renderEngine = templateDefinition.RenderEngine; + + if (renderEngine.IsNullOrWhiteSpace()) + { + renderEngine = Options.DefaultRenderingEngine; + } + + var providerType = Options.RenderingEngines.GetOrDefault(renderEngine); + + if (providerType != null && typeof(ITemplateRenderingEngine).IsAssignableFrom(providerType)) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var templateRenderingEngine = (ITemplateRenderingEngine)scope.ServiceProvider.GetRequiredService(providerType); + return await templateRenderingEngine.RenderAsync(templateName, model, cultureName, globalContext); + } + } + + throw new AbpException("There is no rendering engine found with template name: " + templateName); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingCoreModule.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingCoreModule.cs new file mode 100644 index 0000000000..8a908c2ffd --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingCoreModule.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; + +namespace Volo.Abp.TextTemplating +{ + [DependsOn( + typeof(AbpVirtualFileSystemModule), + typeof(AbpLocalizationAbstractionsModule) + )] + public class AbpTextTemplatingCoreModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + AutoAddProvidersAndContributors(context.Services); + } + + private static void AutoAddProvidersAndContributors(IServiceCollection services) + { + var definitionProviders = new List(); + var contentContributors = new List(); + + services.OnRegistred(context => + { + if (typeof(ITemplateDefinitionProvider).IsAssignableFrom(context.ImplementationType)) + { + definitionProviders.Add(context.ImplementationType); + } + + if (typeof(ITemplateContentContributor).IsAssignableFrom(context.ImplementationType)) + { + contentContributors.Add(context.ImplementationType); + } + }); + + services.Configure(options => + { + options.DefinitionProviders.AddIfNotContains(definitionProviders); + options.ContentContributors.AddIfNotContains(contentContributors); + }); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs similarity index 63% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs index b217094974..b3e4561fb1 100644 --- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/AbpTextTemplatingOptions.cs @@ -1,4 +1,6 @@ -using Volo.Abp.Collections; +using System; +using System.Collections.Generic; +using Volo.Abp.Collections; namespace Volo.Abp.TextTemplating { @@ -6,11 +8,15 @@ namespace Volo.Abp.TextTemplating { public ITypeList DefinitionProviders { get; } public ITypeList ContentContributors { get; } + public IDictionary RenderingEngines { get; } + + public string DefaultRenderingEngine { get; set; } public AbpTextTemplatingOptions() { DefinitionProviders = new TypeList(); ContentContributors = new TypeList(); + RenderingEngines = new Dictionary(); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateContentContributor.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateContentContributor.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateContentContributor.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateContentContributor.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateContentProvider.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateContentProvider.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateContentProvider.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateContentProvider.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionContext.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionContext.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionContext.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionContext.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionManager.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionProvider.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionProvider.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateDefinitionProvider.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateDefinitionProvider.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateRenderer.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateRenderer.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/ITemplateRenderer.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateRenderer.cs diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateRenderingEngine.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateRenderingEngine.cs new file mode 100644 index 0000000000..f55dd03a1b --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/ITemplateRenderingEngine.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace Volo.Abp.TextTemplating +{ + public interface ITemplateRenderingEngine + { + string Name { get; } + + /// + /// Renders a text template. + /// + /// The template name + /// An optional model object that is used in the template + /// Culture name. Uses the if not specified + /// A dictionary which can be used to import global objects to the template + /// + Task RenderAsync( + [NotNull] string templateName, + [CanBeNull] object model = null, + [CanBeNull] string cultureName = null, + [CanBeNull] Dictionary globalContext = null + ); + } +} diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateContentContributorContext.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentContributorContext.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateContentContributorContext.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentContributorContext.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateContentProvider.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentProvider.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateContentProvider.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateContentProvider.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinition.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinition.cs similarity index 88% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinition.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinition.cs index 948c1712db..984bd8885b 100644 --- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinition.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinition.cs @@ -37,6 +37,9 @@ namespace Volo.Abp.TextTemplating [CanBeNull] public string DefaultCultureName { get; } + [CanBeNull] + public string RenderEngine { get; set; } + /// /// Gets/sets a key-value on the . /// @@ -84,5 +87,14 @@ namespace Volo.Abp.TextTemplating Properties[key] = value; return this; } + + /// + /// Sets the Render Engine of . + /// + public virtual TemplateDefinition WithRenderEngine(string renderEngine) + { + RenderEngine = renderEngine; + return this; + } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionContext.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionContext.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionContext.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionContext.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionExtensions.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionExtensions.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionExtensions.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionExtensions.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionManager.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionProvider.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionProvider.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateDefinitionProvider.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateDefinitionProvider.cs diff --git a/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateRenderingEngineBase.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateRenderingEngineBase.cs new file mode 100644 index 0000000000..4606e434ad --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/TemplateRenderingEngineBase.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.Localization; + +namespace Volo.Abp.TextTemplating +{ + public abstract class TemplateRenderingEngineBase : ITemplateRenderingEngine + { + public abstract string Name { get; } + + protected readonly ITemplateDefinitionManager TemplateDefinitionManager; + protected readonly ITemplateContentProvider TemplateContentProvider; + protected readonly IStringLocalizerFactory StringLocalizerFactory; + + public TemplateRenderingEngineBase( + ITemplateDefinitionManager templateDefinitionManager, + ITemplateContentProvider templateContentProvider, + IStringLocalizerFactory stringLocalizerFactory) + { + TemplateDefinitionManager = templateDefinitionManager; + TemplateContentProvider = templateContentProvider; + StringLocalizerFactory = stringLocalizerFactory; + } + + public abstract Task RenderAsync(string templateName, object model = null, string cultureName = null, Dictionary globalContext = null); + + protected virtual async Task GetContentOrNullAsync(TemplateDefinition templateDefinition) + { + return await TemplateContentProvider.GetContentOrNullAsync(templateDefinition); + } + + protected virtual IStringLocalizer GetLocalizerOrNull(TemplateDefinition templateDefinition) + { + if (templateDefinition.LocalizationResource != null) + { + return StringLocalizerFactory.Create(templateDefinition.LocalizationResource); + } + + return StringLocalizerFactory.CreateDefaultOrNull(); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/FileInfoLocalizedTemplateContentReader.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReader.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReader.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReader.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReaderFactory.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReaderFactory.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReaderFactory.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/ILocalizedTemplateContentReaderFactory.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs similarity index 96% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs index 981d1f8819..cc189e1b3b 100644 --- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory.cs @@ -64,7 +64,8 @@ namespace Volo.Abp.TextTemplating.VirtualFiles if (fileInfo.IsDirectory) { - var folderReader = new VirtualFolderLocalizedTemplateContentReader(); + //TODO: Configure file extensions. + var folderReader = new VirtualFolderLocalizedTemplateContentReader(new[] {".tpl", ".cshtml"}); await folderReader.ReadContentsAsync(VirtualFileProvider, virtualPath); return folderReader; } diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/NullLocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/NullLocalizedTemplateContentReader.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/NullLocalizedTemplateContentReader.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/NullLocalizedTemplateContentReader.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContentContributor.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContentContributor.cs similarity index 100% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContentContributor.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContentContributor.cs diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs similarity index 80% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs rename to framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs index 6fc7ff4847..27458d02cc 100644 --- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs +++ b/framework/src/Volo.Abp.TextTemplating.Core/Volo/Abp/TextTemplating/VirtualFiles/VirtualFolderLocalizedTemplateContentReader.cs @@ -9,6 +9,12 @@ namespace Volo.Abp.TextTemplating.VirtualFiles public class VirtualFolderLocalizedTemplateContentReader : ILocalizedTemplateContentReader { private Dictionary _dictionary; + private readonly string[] _fileExtension; + + public VirtualFolderLocalizedTemplateContentReader(string[] fileExtension) + { + _fileExtension = fileExtension; + } public async Task ReadContentsAsync( IVirtualFileProvider virtualFileProvider, @@ -29,7 +35,7 @@ namespace Volo.Abp.TextTemplating.VirtualFiles continue; } - _dictionary.Add(file.Name.RemovePostFix(".tpl"), await file.ReadAsStringAsync()); + _dictionary.Add(file.Name.RemovePostFix(_fileExtension), await file.ReadAsStringAsync()); } } diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xml b/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xml new file mode 100644 index 0000000000..be0de3a908 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xsd b/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xsd new file mode 100644 index 0000000000..3f3946e282 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo.Abp.TextTemplating.Razor.csproj b/framework/src/Volo.Abp.TextTemplating.Razor/Volo.Abp.TextTemplating.Razor.csproj new file mode 100644 index 0000000000..3425fb624a --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo.Abp.TextTemplating.Razor.csproj @@ -0,0 +1,21 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + + + diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions.cs new file mode 100644 index 0000000000..6da3e8b443 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; + +namespace Volo.Abp.TextTemplating.Razor +{ + public class AbpCompiledViewProviderOptions + { + public Dictionary> TemplateReferences { get; } + + public AbpCompiledViewProviderOptions() + { + TemplateReferences = new Dictionary>(); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateCSharpCompiler.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateCSharpCompiler.cs new file mode 100644 index 0000000000..55b0d10f17 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateCSharpCompiler.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.TextTemplating.Razor +{ + public class AbpRazorTemplateCSharpCompiler : ISingletonDependency + { + protected AbpRazorTemplateCSharpCompilerOptions Options { get; } + + public AbpRazorTemplateCSharpCompiler(IOptions options) + { + Options = options.Value; + } + + private static IEnumerable DefaultReferences => new List() + { + Assembly.Load("netstandard"), + Assembly.Load("System.Private.CoreLib"), + Assembly.Load("System.Runtime"), + Assembly.Load("System.Collections"), + Assembly.Load("System.ComponentModel"), + Assembly.Load("System.Linq"), + Assembly.Load("System.Linq.Expressions"), + Assembly.Load("Microsoft.Extensions.DependencyInjection"), + Assembly.Load("Microsoft.Extensions.DependencyInjection.Abstractions"), + Assembly.Load("Microsoft.Extensions.Localization"), + Assembly.Load("Microsoft.Extensions.Localization.Abstractions"), + + typeof(AbpRazorTemplateCSharpCompiler).Assembly + } + .Select(x => MetadataReference.CreateFromFile(x.Location)) + .ToImmutableList(); + + public virtual Stream CreateAssembly(string code, string assemblyName, List references = null, CSharpCompilationOptions options = null) + { + var defaultReferences = DefaultReferences.Concat(Options.References); + try + { + var compilation = CSharpCompilation.Create( + assemblyName, + syntaxTrees: new[] { CreateSyntaxTree(code) }, + references: references != null ? defaultReferences.Concat(references) : defaultReferences, + options ?? GetCompilationOptions()); + + using (var memoryStream = new MemoryStream()) + { + var result = compilation.Emit(memoryStream); + + if (!result.Success) + { + var error = new StringBuilder(); + error.AppendLine("Build failed"); + foreach (var diagnostic in result.Diagnostics) + { + error.AppendLine(diagnostic.ToString()); + } + + throw new Exception(error.ToString()); + } + + memoryStream.Seek(0, SeekOrigin.Begin); + var assemblyStream = new MemoryStream(); + memoryStream.CopyTo(assemblyStream); + + return assemblyStream; + } + } + catch (Exception e) + { + var error = new StringBuilder(); + error.AppendLine("CreateAssembly failed"); + error.AppendLine(e.Message); + throw new Exception(error.ToString()); + } + } + + protected virtual SyntaxTree CreateSyntaxTree(string code) + { + return CSharpSyntaxTree.ParseText(code); + } + + protected virtual CSharpCompilationOptions GetCompilationOptions() + { + var csharpCompilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); + + // Disable 1702 until roslyn turns this off by default + csharpCompilationOptions = csharpCompilationOptions.WithSpecificDiagnosticOptions( + new Dictionary + { + {"CS1701", ReportDiagnostic.Suppress}, // Binding redirects + {"CS1702", ReportDiagnostic.Suppress}, + {"CS1705", ReportDiagnostic.Suppress} + }); + + return csharpCompilationOptions.WithOptimizationLevel(OptimizationLevel.Release); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateCSharpCompilerOptions.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateCSharpCompilerOptions.cs new file mode 100644 index 0000000000..20c1e391e0 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateCSharpCompilerOptions.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; + +namespace Volo.Abp.TextTemplating.Razor +{ + public class AbpRazorTemplateCSharpCompilerOptions + { + public List References { get; } + + public AbpRazorTemplateCSharpCompilerOptions() + { + References = new List(); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateConsts.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateConsts.cs new file mode 100644 index 0000000000..7701a89630 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpRazorTemplateConsts.cs @@ -0,0 +1,9 @@ +namespace Volo.Abp.TextTemplating.Razor +{ + public static class AbpRazorTemplateConsts + { + public const string DefaultNameSpace = "Abp.Razor"; + public const string DefaultClassName = "Template"; + public const string TypeName = DefaultNameSpace + "." + DefaultClassName; + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpTextTemplatingRazorModule.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpTextTemplatingRazorModule.cs new file mode 100644 index 0000000000..446ba00cc1 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/AbpTextTemplatingRazorModule.cs @@ -0,0 +1,23 @@ +using System; +using Volo.Abp.Modularity; + +namespace Volo.Abp.TextTemplating.Razor +{ + [DependsOn( + typeof(AbpTextTemplatingCoreModule) + )] + public class AbpTextTemplatingRazorModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + if (options.DefaultRenderingEngine.IsNullOrWhiteSpace()) + { + options.DefaultRenderingEngine = RazorTemplateRenderingEngine.EngineName; + } + options.RenderingEngines[RazorTemplateRenderingEngine.EngineName] = typeof(RazorTemplateRenderingEngine); + }); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs new file mode 100644 index 0000000000..c743252456 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpCompiledViewProvider.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.CodeAnalysis; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.TextTemplating.Razor +{ + public class DefaultAbpCompiledViewProvider : IAbpCompiledViewProvider, ITransientDependency + { + private static readonly ConcurrentDictionary CachedAssembles = new ConcurrentDictionary(); + + private readonly AbpCompiledViewProviderOptions _options; + private readonly AbpRazorTemplateCSharpCompiler _razorTemplateCSharpCompiler; + private readonly IAbpRazorProjectEngineFactory _razorProjectEngineFactory; + private readonly ITemplateContentProvider _templateContentProvider; + + public DefaultAbpCompiledViewProvider( + IOptions options, + IAbpRazorProjectEngineFactory razorProjectEngineFactory, + AbpRazorTemplateCSharpCompiler razorTemplateCSharpCompiler, + ITemplateContentProvider templateContentProvider) + { + _options = options.Value; + + _razorProjectEngineFactory = razorProjectEngineFactory; + _razorTemplateCSharpCompiler = razorTemplateCSharpCompiler; + _templateContentProvider = templateContentProvider; + } + + public virtual async Task GetAssemblyAsync(TemplateDefinition templateDefinition) + { + async Task CreateAssembly(string content) + { + using (var assemblyStream = await GetAssemblyStreamAsync(templateDefinition, content)) + { + return Assembly.Load(await assemblyStream.GetAllBytesAsync()); + } + } + + var templateContent = await _templateContentProvider.GetContentOrNullAsync(templateDefinition); + return CachedAssembles.GetOrAdd((templateDefinition.Name + templateContent).ToMd5(), await CreateAssembly(templateContent)); + } + + protected virtual async Task GetAssemblyStreamAsync(TemplateDefinition templateDefinition, string templateContent) + { + var razorProjectEngine = await _razorProjectEngineFactory.CreateAsync(builder => + { + builder.SetNamespace(AbpRazorTemplateConsts.DefaultNameSpace); + builder.ConfigureClass((document, node) => + { + node.ClassName = AbpRazorTemplateConsts.DefaultClassName; + }); + }); + + var codeDocument = razorProjectEngine.Process( + RazorSourceDocument.Create(templateContent, templateDefinition.Name), null, + new List(), new List()); + + var cSharpDocument = codeDocument.GetCSharpDocument(); + + var templateReferences = _options.TemplateReferences + .GetOrDefault(templateDefinition.Name) + ?.Select(x => x) + .Cast() + .ToList(); + + return _razorTemplateCSharpCompiler.CreateAssembly(cSharpDocument.GeneratedCode, templateDefinition.Name, templateReferences); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpRazorProjectEngineFactory.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpRazorProjectEngineFactory.cs new file mode 100644 index 0000000000..eb6d851f49 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/DefaultAbpRazorProjectEngineFactory.cs @@ -0,0 +1,20 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Language; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.TextTemplating.Razor +{ + public class DefaultAbpRazorProjectEngineFactory : IAbpRazorProjectEngineFactory, ITransientDependency + { + public virtual async Task CreateAsync(Action configure = null) + { + return RazorProjectEngine.Create(await CreateRazorConfigurationAsync(), EmptyProjectFileSystem.Empty, configure); + } + + protected virtual Task CreateRazorConfigurationAsync() + { + return Task.FromResult(RazorConfiguration.Default); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/EmptyProjectFileSystem.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/EmptyProjectFileSystem.cs new file mode 100644 index 0000000000..496e86e977 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/EmptyProjectFileSystem.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Razor.Language; + +namespace Volo.Abp.TextTemplating.Razor +{ + internal class EmptyProjectFileSystem : RazorProjectFileSystem + { + internal static readonly RazorProjectFileSystem Empty = new EmptyProjectFileSystem(); + + public override IEnumerable EnumerateItems(string basePath) + { + NormalizeAndEnsureValidPath(basePath); + return Enumerable.Empty(); + } + + [Obsolete("Use GetItem(string path, string fileKind) instead.")] + public override RazorProjectItem GetItem(string path) + { + return GetItem(path, fileKind: null); + } + + public override RazorProjectItem GetItem(string path, string fileKind) + { + NormalizeAndEnsureValidPath(path); + return new NotFoundProjectItem(string.Empty, path, fileKind); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IAbpCompiledViewProvider.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IAbpCompiledViewProvider.cs new file mode 100644 index 0000000000..ba5e96d2fa --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IAbpCompiledViewProvider.cs @@ -0,0 +1,10 @@ +using System.Reflection; +using System.Threading.Tasks; + +namespace Volo.Abp.TextTemplating.Razor +{ + public interface IAbpCompiledViewProvider + { + Task GetAssemblyAsync(TemplateDefinition templateDefinition); + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IAbpRazorProjectEngineFactory.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IAbpRazorProjectEngineFactory.cs new file mode 100644 index 0000000000..c96b171f59 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IAbpRazorProjectEngineFactory.cs @@ -0,0 +1,11 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Language; + +namespace Volo.Abp.TextTemplating.Razor +{ + public interface IAbpRazorProjectEngineFactory + { + Task CreateAsync(Action configure = null); + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IRazorTemplatePage.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IRazorTemplatePage.cs new file mode 100644 index 0000000000..fc386c3353 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/IRazorTemplatePage.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using Microsoft.Extensions.Localization; + +namespace Volo.Abp.TextTemplating.Razor +{ + public interface IRazorTemplatePage : IRazorTemplatePage + { + TModel Model { get; set; } + } + + public interface IRazorTemplatePage + { + IServiceProvider ServiceProvider { get; set; } + + IStringLocalizer Localizer { get; set; } + + HtmlEncoder HtmlEncoder { get; set; } + + JavaScriptEncoder JavaScriptEncoder { get; set; } + + UrlEncoder UrlEncoder { get; set; } + + Dictionary GlobalContext { get; set; } + + string Body { get; set; } + + Task ExecuteAsync(); + + Task GetOutputAsync(); + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/NotFoundProjectItem.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/NotFoundProjectItem.cs new file mode 100644 index 0000000000..735522bd09 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/NotFoundProjectItem.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; +using Microsoft.AspNetCore.Razor.Language; + +namespace Volo.Abp.TextTemplating.Razor +{ + internal class NotFoundProjectItem : RazorProjectItem + { + public NotFoundProjectItem(string basePath, string path, string fileKind) + { + BasePath = basePath; + FilePath = path; + FileKind = fileKind ?? FileKinds.GetFileKindFromFilePath(path); + } + + public override string BasePath { get; } + + public override string FilePath { get; } + + public override string FileKind { get; } + + public override bool Exists => false; + + public override string PhysicalPath => throw new NotSupportedException(); + + public override Stream Read() => throw new NotSupportedException(); + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateDefinitionExtensions.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateDefinitionExtensions.cs new file mode 100644 index 0000000000..343905ecec --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateDefinitionExtensions.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; + +namespace Volo.Abp.TextTemplating.Razor +{ + public static class RazorTemplateDefinitionExtensions + { + public static TemplateDefinition WithRazorEngine([NotNull] this TemplateDefinition templateDefinition) + { + return templateDefinition.WithRenderEngine(RazorTemplateRenderingEngine.EngineName); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplatePageBase.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplatePageBase.cs new file mode 100644 index 0000000000..9854775a25 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplatePageBase.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using Microsoft.Extensions.Localization; + +namespace Volo.Abp.TextTemplating.Razor +{ + public abstract class RazorTemplatePageBase : RazorTemplatePageBase, IRazorTemplatePage + { + public TModel Model { get; set; } + } + + public abstract class RazorTemplatePageBase : IRazorTemplatePage + { + public Dictionary GlobalContext { get; set; } + + public IServiceProvider ServiceProvider { get; set; } + + public IStringLocalizer Localizer { get; set; } + + public HtmlEncoder HtmlEncoder { get; set; } + + public JavaScriptEncoder JavaScriptEncoder { get; set; } + + public UrlEncoder UrlEncoder { get; set; } + + public string Body { get; set; } + + private readonly StringBuilder _stringBuilder = new StringBuilder(); + + private AttributeInfo _attributeInfo; + + public virtual void WriteLiteral(string literal = null) + { + _stringBuilder.Append(literal); + } + + public virtual void Write(object obj = null) + { + _stringBuilder.Append(obj); + } + + public virtual void BeginWriteAttribute(string name, string prefix, int prefixOffset, string suffix, int suffixOffset, int attributeValuesCount) + { + _attributeInfo = new AttributeInfo(name, prefix, prefixOffset, suffix, suffixOffset, attributeValuesCount); + WriteLiteral(prefix); + } + + public virtual void WriteAttributeValue(string prefix, int prefixOffset, object value, int valueOffset, int valueLength, bool isLiteral) + { + if (_attributeInfo.AttributeValuesCount == 1) + { + if (IsBoolFalseOrNullValue(prefix, value)) + { + // Value is either null or the bool 'false' with no prefix; don't render the attribute. + _attributeInfo.Suppressed = true; + return; + } + + // We are not omitting the attribute. Write the prefix. + WriteLiteral(_attributeInfo.Prefix); + + if (IsBoolTrueWithEmptyPrefixValue(prefix, value)) + { + // The value is just the bool 'true', write the attribute name instead of the string 'True'. + value = _attributeInfo.Name; + } + } + + // This block handles two cases. + // 1. Single value with prefix. + // 2. Multiple values with or without prefix. + if (value != null) + { + if (!string.IsNullOrEmpty(prefix)) + { + WriteLiteral(prefix); + } + + WriteUnprefixedAttributeValue(value, isLiteral); + } + + _stringBuilder.Append(prefix); + _stringBuilder.Append(value); + } + + public virtual void EndWriteAttribute() + { + if (!_attributeInfo.Suppressed) + { + WriteLiteral(_attributeInfo.Suffix); + } + } + + public virtual Task ExecuteAsync() + { + return Task.CompletedTask; + } + + public virtual Task GetOutputAsync() + { + return Task.FromResult(_stringBuilder.ToString()); + } + + private void WriteUnprefixedAttributeValue(object value, bool isLiteral) + { + var stringValue = value as string; + + // The extra branching here is to ensure that we call the Write*To(string) overload where possible. + if (isLiteral && stringValue != null) + { + WriteLiteral(stringValue); + } + else if (isLiteral) + { + //WriteLiteral(value); + _stringBuilder.Append(value); + } + else if (stringValue != null) + { + Write(stringValue); + } + else + { + Write(value); + } + } + + private bool IsBoolFalseOrNullValue(string prefix, object value) + { + return string.IsNullOrEmpty(prefix) && (value == null || (value is bool b && !b)); + } + + private bool IsBoolTrueWithEmptyPrefixValue(string prefix, object value) + { + // If the value is just the bool 'true', use the attribute name as the value. + return string.IsNullOrEmpty(prefix) && (value is bool b && b); + } + + private struct AttributeInfo + { + public AttributeInfo( + string name, + string prefix, + int prefixOffset, + string suffix, + int suffixOffset, + int attributeValuesCount) + { + Name = name; + Prefix = prefix; + PrefixOffset = prefixOffset; + Suffix = suffix; + SuffixOffset = suffixOffset; + AttributeValuesCount = attributeValuesCount; + + Suppressed = false; + } + + public int AttributeValuesCount { get; } + + public string Name { get; } + + public string Prefix { get; } + + public int PrefixOffset { get; } + + public string Suffix { get; } + + public int SuffixOffset { get; } + + public bool Suppressed { get; set; } + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs new file mode 100644 index 0000000000..3ef2d69fd6 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Razor/Volo/Abp/TextTemplating/Razor/RazorTemplateRenderingEngine.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Localization; + +namespace Volo.Abp.TextTemplating.Razor +{ + public class RazorTemplateRenderingEngine : TemplateRenderingEngineBase, ITransientDependency + { + public const string EngineName = "Razor"; + public override string Name => EngineName; + + protected readonly IServiceScopeFactory ServiceScopeFactory; + protected readonly IAbpCompiledViewProvider AbpCompiledViewProvider; + + public RazorTemplateRenderingEngine( + IServiceScopeFactory serviceScopeFactory, + IAbpCompiledViewProvider abpCompiledViewProvider, + ITemplateDefinitionManager templateDefinitionManager, + ITemplateContentProvider templateContentProvider, + IStringLocalizerFactory stringLocalizerFactory) + : base(templateDefinitionManager, templateContentProvider, stringLocalizerFactory) + { + ServiceScopeFactory = serviceScopeFactory; + AbpCompiledViewProvider = abpCompiledViewProvider; + } + + public override async Task RenderAsync( + [NotNull] string templateName, + [CanBeNull] object model = null, + [CanBeNull] string cultureName = null, + [CanBeNull] Dictionary globalContext = null) + { + Check.NotNullOrWhiteSpace(templateName, nameof(templateName)); + + if (globalContext == null) + { + globalContext = new Dictionary(); + } + + if (cultureName == null) + { + return await RenderInternalAsync( + templateName, + null, + globalContext, + model + ); + } + else + { + using (CultureHelper.Use(cultureName)) + { + return await RenderInternalAsync( + templateName, + null, + globalContext, + model + ); + } + } + } + + protected virtual async Task RenderInternalAsync( + string templateName, + string body, + Dictionary globalContext, + object model = null) + { + var templateDefinition = TemplateDefinitionManager.Get(templateName); + + var renderedContent = await RenderSingleTemplateAsync( + templateDefinition, + body, + globalContext, + model + ); + + if (templateDefinition.Layout != null) + { + renderedContent = await RenderInternalAsync( + templateDefinition.Layout, + renderedContent, + globalContext + ); + } + + return renderedContent; + } + + protected virtual async Task RenderSingleTemplateAsync( + TemplateDefinition templateDefinition, + string body, + Dictionary globalContext, + object model = null) + { + return await RenderTemplateContentWithRazorAsync( + templateDefinition, + body, + globalContext, + model + ); + } + + protected virtual async Task RenderTemplateContentWithRazorAsync( + TemplateDefinition templateDefinition, + string body, + Dictionary globalContext, + object model = null) + { + var assembly = await AbpCompiledViewProvider.GetAssemblyAsync(templateDefinition); + var templateType = assembly.GetType(AbpRazorTemplateConsts.TypeName); + var template = (IRazorTemplatePage) Activator.CreateInstance(templateType); + + using (var scope = ServiceScopeFactory.CreateScope()) + { + var modelType = templateType + .GetInterfaces() + .Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IRazorTemplatePage<>)) + .Select(x => x.GenericTypeArguments.FirstOrDefault()) + .FirstOrDefault(); + + if (modelType != null) + { + GetType().GetMethod(nameof(SetModel), BindingFlags.Instance | BindingFlags.NonPublic) + ?.MakeGenericMethod(modelType).Invoke(this, new[] {template, model}); + } + + template.ServiceProvider = scope.ServiceProvider; + template.Localizer = GetLocalizerOrNull(templateDefinition); + template.HtmlEncoder = scope.ServiceProvider.GetService(); + template.JavaScriptEncoder = scope.ServiceProvider.GetService(); + template.UrlEncoder = scope.ServiceProvider.GetService(); + template.Body = body; + template.GlobalContext = globalContext; + + await template.ExecuteAsync(); + + return await template.GetOutputAsync(); + } + } + + private void SetModel(IRazorTemplatePage razorTemplatePage, object model = null) + { + if (razorTemplatePage is IRazorTemplatePage razorTemplatePageWithModel) + { + razorTemplatePageWithModel.Model = (TModel)model; + } + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xml b/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xml new file mode 100644 index 0000000000..be0de3a908 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xsd b/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xsd new file mode 100644 index 0000000000..3f3946e282 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Scriban/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.TextTemplating.Scriban/Volo.Abp.TextTemplating.Scriban.csproj b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo.Abp.TextTemplating.Scriban.csproj new file mode 100644 index 0000000000..4581050b6a --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo.Abp.TextTemplating.Scriban.csproj @@ -0,0 +1,19 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + diff --git a/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/AbpTextTemplatingScribanModule.cs b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/AbpTextTemplatingScribanModule.cs new file mode 100644 index 0000000000..fb05325a95 --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/AbpTextTemplatingScribanModule.cs @@ -0,0 +1,19 @@ +using Volo.Abp.Modularity; + +namespace Volo.Abp.TextTemplating.Scriban +{ + [DependsOn( + typeof(AbpTextTemplatingCoreModule) + )] + public class AbpTextTemplatingScribanModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.DefaultRenderingEngine = ScribanTemplateRenderingEngine.EngineName; + options.RenderingEngines[ScribanTemplateRenderingEngine.EngineName] = typeof(ScribanTemplateRenderingEngine); + }); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateDefinitionExtensions.cs b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateDefinitionExtensions.cs new file mode 100644 index 0000000000..c003ed384c --- /dev/null +++ b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateDefinitionExtensions.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; + +namespace Volo.Abp.TextTemplating.Scriban +{ + public static class ScribanTemplateDefinitionExtensions + { + public static TemplateDefinition WithScribanEngine([NotNull] this TemplateDefinition templateDefinition) + { + return templateDefinition.WithRenderEngine(ScribanTemplateRenderingEngine.EngineName); + } + } +} diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateLocalizer.cs b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateLocalizer.cs similarity index 91% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateLocalizer.cs rename to framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateLocalizer.cs index 4e4a1e4833..e280cd194a 100644 --- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateLocalizer.cs +++ b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateLocalizer.cs @@ -7,13 +7,13 @@ using Scriban; using Scriban.Runtime; using Scriban.Syntax; -namespace Volo.Abp.TextTemplating +namespace Volo.Abp.TextTemplating.Scriban { - public class TemplateLocalizer : IScriptCustomFunction + public class ScribanTemplateLocalizer : IScriptCustomFunction { private readonly IStringLocalizer _localizer; - public TemplateLocalizer(IStringLocalizer localizer) + public ScribanTemplateLocalizer(IStringLocalizer localizer) { _localizer = localizer; } diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderingEngine.cs similarity index 73% rename from framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs rename to framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderingEngine.cs index 1d89dc3b68..81038e2d0f 100644 --- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/TemplateRenderer.cs +++ b/framework/src/Volo.Abp.TextTemplating.Scriban/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRenderingEngine.cs @@ -1,33 +1,28 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Options; using Scriban; using Scriban.Runtime; using Volo.Abp.DependencyInjection; using Volo.Abp.Localization; -namespace Volo.Abp.TextTemplating +namespace Volo.Abp.TextTemplating.Scriban { - public class TemplateRenderer : ITemplateRenderer, ITransientDependency + public class ScribanTemplateRenderingEngine : TemplateRenderingEngineBase, ITransientDependency { - private readonly ITemplateContentProvider _templateContentProvider; - private readonly ITemplateDefinitionManager _templateDefinitionManager; - private readonly IStringLocalizerFactory _stringLocalizerFactory; + public const string EngineName = "Scriban"; + public override string Name => EngineName; - public TemplateRenderer( - ITemplateContentProvider templateContentProvider, + public ScribanTemplateRenderingEngine( ITemplateDefinitionManager templateDefinitionManager, + ITemplateContentProvider templateContentProvider, IStringLocalizerFactory stringLocalizerFactory) + : base(templateDefinitionManager, templateContentProvider, stringLocalizerFactory) { - _templateContentProvider = templateContentProvider; - _templateDefinitionManager = templateDefinitionManager; - _stringLocalizerFactory = stringLocalizerFactory; } - public virtual async Task RenderAsync( + public override async Task RenderAsync( [NotNull] string templateName, [CanBeNull] object model = null, [CanBeNull] string cultureName = null, @@ -66,7 +61,7 @@ namespace Volo.Abp.TextTemplating Dictionary globalContext, object model = null) { - var templateDefinition = _templateDefinitionManager.Get(templateName); + var templateDefinition = TemplateDefinitionManager.Get(templateName); var renderedContent = await RenderSingleTemplateAsync( templateDefinition, @@ -91,10 +86,7 @@ namespace Volo.Abp.TextTemplating Dictionary globalContext, object model = null) { - var rawTemplateContent = await _templateContentProvider - .GetContentOrNullAsync( - templateDefinition - ); + var rawTemplateContent = await GetContentOrNullAsync(templateDefinition); return await RenderTemplateContentWithScribanAsync( templateDefinition, @@ -140,7 +132,7 @@ namespace Volo.Abp.TextTemplating var localizer = GetLocalizerOrNull(templateDefinition); if (localizer != null) { - scriptObject.SetValue("L", new TemplateLocalizer(localizer), true); + scriptObject.SetValue("L", new ScribanTemplateLocalizer(localizer), true); } context.PushGlobal(scriptObject); @@ -148,15 +140,5 @@ namespace Volo.Abp.TextTemplating return context; } - - private IStringLocalizer GetLocalizerOrNull(TemplateDefinition templateDefinition) - { - if (templateDefinition.LocalizationResource != null) - { - return _stringLocalizerFactory.Create(templateDefinition.LocalizationResource); - } - - return _stringLocalizerFactory.CreateDefaultOrNull(); - } } } diff --git a/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj b/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj index 506b086a88..3af0ba984d 100644 --- a/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj +++ b/framework/src/Volo.Abp.TextTemplating/Volo.Abp.TextTemplating.csproj @@ -5,22 +5,11 @@ netstandard2.0 - Volo.Abp.TextTemplating - Volo.Abp.TextTemplating - $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; - false - false - false - - - - - - + diff --git a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingModule.cs b/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingModule.cs index 8d76391829..236d9a1593 100644 --- a/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingModule.cs +++ b/framework/src/Volo.Abp.TextTemplating/Volo/Abp/TextTemplating/AbpTextTemplatingModule.cs @@ -1,46 +1,13 @@ using System; -using System.Collections.Generic; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Localization; using Volo.Abp.Modularity; -using Volo.Abp.VirtualFileSystem; +using Volo.Abp.TextTemplating.Scriban; namespace Volo.Abp.TextTemplating { - [DependsOn( - typeof(AbpVirtualFileSystemModule), - typeof(AbpLocalizationAbstractionsModule) - )] + [Obsolete("This module will be removed in the future. Please use AbpTextTemplatingScribanModule or AbpTextTemplatingRazorModule.")] + [DependsOn(typeof(AbpTextTemplatingScribanModule))] public class AbpTextTemplatingModule : AbpModule { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - AutoAddProvidersAndContributors(context.Services); - } - private static void AutoAddProvidersAndContributors(IServiceCollection services) - { - var definitionProviders = new List(); - var contentContributors = new List(); - - services.OnRegistred(context => - { - if (typeof(ITemplateDefinitionProvider).IsAssignableFrom(context.ImplementationType)) - { - definitionProviders.Add(context.ImplementationType); - } - - if (typeof(ITemplateContentContributor).IsAssignableFrom(context.ImplementationType)) - { - contentContributors.Add(context.ImplementationType); - } - }); - - services.Configure(options => - { - options.DefinitionProviders.AddIfNotContains(definitionProviders); - options.ContentContributors.AddIfNotContains(contentContributors); - }); - } } } diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AmbientDataContextAmbientScopeProvider.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AmbientDataContextAmbientScopeProvider.cs index 822361638e..1d83278bf1 100644 --- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AmbientDataContextAmbientScopeProvider.cs +++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/AmbientDataContextAmbientScopeProvider.cs @@ -62,8 +62,7 @@ namespace Volo.Abp.Threading private ScopeItem GetCurrentItem(string contextKey) { - var objKey = _dataContext.GetData(contextKey) as string; - return objKey != null ? ScopeDictionary.GetOrDefault(objKey) : null; + return _dataContext.GetData(contextKey) is string objKey ? ScopeDictionary.GetOrDefault(objKey) : null; } private class ScopeItem diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/fi.json b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/fi.json new file mode 100644 index 0000000000..f7301d9c31 --- /dev/null +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/fi.json @@ -0,0 +1,7 @@ +{ + "culture": "fi", + "texts": { + "DisplayName:Abp.Timing.Timezone": "Aikavyöhyke", + "Description:Abp.Timing.Timezone": "Levityksen aikavyöhyke" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/hi.json b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/hi.json new file mode 100644 index 0000000000..8878cf64d9 --- /dev/null +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/hi.json @@ -0,0 +1,7 @@ +{ + "culture": "hi", + "texts": { + "DisplayName:Abp.Timing.Timezone": "समय क्षेत्र", + "Description:Abp.Timing.Timezone": "आवेदन समय क्षेत्र" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/it.json b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/it.json new file mode 100644 index 0000000000..107f1ebb3b --- /dev/null +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/it.json @@ -0,0 +1,7 @@ +{ + "culture": "it", + "texts": { + "DisplayName:Abp.Timing.Timezone": "Fuso orario", + "Description:Abp.Timing.Timezone": "Fuso orario dell'applicazione" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs index 63f4d7239d..f269c34598 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuItem.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; using JetBrains.Annotations; +using Volo.Abp.SimpleStateChecking; namespace Volo.Abp.UI.Navigation { - public class ApplicationMenuItem : IHasMenuItems + public class ApplicationMenuItem : IHasMenuItems, IHasSimpleStateCheckers { private string _displayName; @@ -72,8 +73,11 @@ namespace Volo.Abp.UI.Navigation public ApplicationMenuItemList Items { get; } [CanBeNull] + [Obsolete("Use RequirePermissions extension method.")] public string RequiredPermissionName { get; set; } + public List> StateCheckers { get; } + /// /// Can be used to store a custom object related to this menu item. Optional. /// @@ -114,7 +118,7 @@ namespace Volo.Abp.UI.Navigation ElementId = elementId ?? GetDefaultElementId(); CssClass = cssClass; RequiredPermissionName = requiredPermissionName; - + StateCheckers = new List>(); Items = new ApplicationMenuItemList(); } diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/fi.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/fi.json new file mode 100644 index 0000000000..41a34208e5 --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/fi.json @@ -0,0 +1,6 @@ +{ + "culture": "fi", + "texts": { + "Menu:Administration": "Hallinto" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/hi.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/hi.json new file mode 100644 index 0000000000..6b9ac8ab4c --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/hi.json @@ -0,0 +1,6 @@ +{ + "culture": "hi", + "texts": { + "Menu:Administration": "शासन प्रबंध" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/it.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/it.json new file mode 100644 index 0000000000..d8a21ec090 --- /dev/null +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/it.json @@ -0,0 +1,6 @@ +{ + "culture": "it", + "texts": { + "Menu:Administration": "Amministrazione" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs index 960389230e..0b52aff7b8 100644 --- a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs +++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/MenuManager.cs @@ -2,10 +2,10 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.Authorization.Permissions; using Volo.Abp.DependencyInjection; +using Volo.Abp.SimpleStateChecking; namespace Volo.Abp.UI.Navigation { @@ -13,13 +13,15 @@ namespace Volo.Abp.UI.Navigation { protected AbpNavigationOptions Options { get; } protected IHybridServiceScopeFactory ServiceScopeFactory { get; } - + protected ISimpleStateCheckerManager SimpleStateCheckerManager { get; } public MenuManager( IOptions options, - IHybridServiceScopeFactory serviceScopeFactory) + IHybridServiceScopeFactory serviceScopeFactory, + ISimpleStateCheckerManager simpleStateCheckerManager) { - ServiceScopeFactory = serviceScopeFactory; Options = options.Value; + ServiceScopeFactory = serviceScopeFactory; + SimpleStateCheckerManager = simpleStateCheckerManager; } public async Task GetAsync(string name) @@ -28,14 +30,17 @@ namespace Volo.Abp.UI.Navigation using (var scope = ServiceScopeFactory.CreateScope()) { - var context = new MenuConfigurationContext(menu, scope.ServiceProvider); - - foreach (var contributor in Options.MenuContributors) + using (RequirePermissionsSimpleBatchStateChecker.Use(new RequirePermissionsSimpleBatchStateChecker())) { - await contributor.ConfigureMenuAsync(context); - } + var context = new MenuConfigurationContext(menu, scope.ServiceProvider); - await CheckPermissionsAsync(scope.ServiceProvider, menu); + foreach (var contributor in Options.MenuContributors) + { + await contributor.ConfigureMenuAsync(context); + } + + await CheckPermissionsAsync(scope.ServiceProvider, menu); + } } NormalizeMenu(menu); @@ -45,18 +50,26 @@ namespace Volo.Abp.UI.Navigation protected virtual async Task CheckPermissionsAsync(IServiceProvider serviceProvider, IHasMenuItems menuWithItems) { - var requiredPermissionItems = new List(); - GetRequiredPermissionNameMenus(menuWithItems, requiredPermissionItems); + var allMenuItems = new List(); + GetAllMenuItems(menuWithItems, allMenuItems); - if (requiredPermissionItems.Any()) + foreach (var item in allMenuItems) { - var permissionChecker = serviceProvider.GetRequiredService(); - var grantResult = await permissionChecker.IsGrantedAsync(requiredPermissionItems.Select(x => x.RequiredPermissionName).Distinct().ToArray()); + if (!item.RequiredPermissionName.IsNullOrWhiteSpace()) + { + item.RequirePermissions(item.RequiredPermissionName); + } + } + var checkPermissionsMenuItems = allMenuItems.Where(x => x.StateCheckers.Any()).ToArray(); + + if (checkPermissionsMenuItems.Any()) + { var toBeDeleted = new HashSet(); - foreach (var menu in requiredPermissionItems) + var result = await SimpleStateCheckerManager.IsEnabledAsync(checkPermissionsMenuItems); + foreach (var menu in checkPermissionsMenuItems) { - if (grantResult.Result[menu.RequiredPermissionName!] != PermissionGrantResult.Granted) + if (!result[menu]) { toBeDeleted.Add(menu); } @@ -66,16 +79,12 @@ namespace Volo.Abp.UI.Navigation } } - protected virtual void GetRequiredPermissionNameMenus(IHasMenuItems menuWithItems, List output) + protected virtual void GetAllMenuItems(IHasMenuItems menuWithItems, List output) { foreach (var item in menuWithItems.Items) { - if (!item.RequiredPermissionName.IsNullOrWhiteSpace()) - { - output.Add(item); - } - - GetRequiredPermissionNameMenus(item, output); + output.Add(item); + GetAllMenuItems(item, output); } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json index 076d4b2517..ff846b3f18 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json @@ -11,7 +11,7 @@ "Close": "Cerrar", "Save": "Guardar", "SavingWithThreeDot": "Guardando...", - "Actions": "Acciones", + "Actions": "Opciones", "Delete": "Borrar", "Edit": "Editar", "Refresh": "Actualizar", @@ -20,10 +20,10 @@ "ProcessingWithThreeDot": "Procesando...", "LoadingWithThreeDot": "Cargardo...", "Welcome": "Bienvenido", - "Login": "Iniciar Sesión", + "Login": "Iniciar sesión", "Register": "Registrarse", "Logout": "Cerrar sesión", - "Submit": "Enviar", + "Submit": "Guardar", "Back": "Volver", "PagerSearch": "Buscar", "PagerNext": "Siguiente", @@ -37,11 +37,11 @@ "NoDataAvailableInDatatable": "No hay datos disponibles", "Total": "Total", "Selected": "Seleccionado", - "PagerShowMenuEntries": "Mostrar _MENU_ entradas", - "DatatableActionDropdownDefaultText": "Acciones", + "PagerShowMenuEntries": "Mostrar _MENU_ registros", + "DatatableActionDropdownDefaultText": "Opciones", "ChangePassword": "Cambiar contraseña", "PersonalInfo": "Mi perfil", - "AreYouSureYouWantToCancelEditingWarningMessage": "Tu tienes cambios sin guardar", + "AreYouSureYouWantToCancelEditingWarningMessage": "Tienes cambios sin guardar", "GoHomePage": "Ir a la página principal", "GoBack": "Volver atrás", "Search": "Buscar", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json new file mode 100644 index 0000000000..844752e093 --- /dev/null +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json @@ -0,0 +1,52 @@ +{ + "culture": "fi", + "texts": { + "Languages": "Kieli (kielet", + "AreYouSure": "Oletko varma?", + "Cancel": "Peruuttaa", + "Clear": "Asia selvä", + "Yes": "Joo", + "No": "Ei", + "Ok": "Ok", + "Close": "kiinni", + "Save": "Tallentaa", + "SavingWithThreeDot": "Tallentaa...", + "Actions": "Toiminnot", + "Delete": "Poistaa", + "Edit": "Muokata", + "Refresh": "virkistää", + "Language": "Kieli", + "LoadMore": "Lataa lisää", + "ProcessingWithThreeDot": "Käsitellään ...", + "LoadingWithThreeDot": "Ladataan...", + "Welcome": "Tervetuloa", + "Login": "Kirjaudu sisään", + "Register": "Rekisteröidy", + "Logout": "Kirjautua ulos", + "Submit": "Lähetä", + "Back": "Takaisin", + "PagerSearch": "Hae", + "PagerNext": "Seuraava", + "PagerPrevious": "Edellinen", + "PagerFirst": "Ensimmäinen", + "PagerLast": "Kestää", + "PagerInfo": "Näytetään _START_ - _END_ / _TOTAL_ merkinnästä", + "PagerInfo{0}{1}{2}": "Näytetään {0} - {1} / {2} merkinnästä", + "PagerInfoEmpty": "Näytetään 0 - 0/0 merkinnästä", + "PagerInfoFiltered": "(suodatettu _MAX_ merkinnän kokonaismäärästä)", + "NoDataAvailableInDatatable": "Tietoja ei ole käytettävissä", + "Total": "kaikki yhteensä", + "Selected": "valittu", + "PagerShowMenuEntries": "Näytä _MENU_ merkinnät", + "DatatableActionDropdownDefaultText": "Toiminnot", + "ChangePassword": "Vaihda salasana", + "PersonalInfo": "Profiilini", + "AreYouSureYouWantToCancelEditingWarningMessage": "Sinulla on tallentamattomia muutoksia.", + "GoHomePage": "Siirry kotisivulle", + "GoBack": "Mene takaisin", + "Search": "Hae", + "ItemWillBeDeletedMessageWithFormat": "{0} poistetaan!", + "ItemWillBeDeletedMessage": "Tämä kohde poistetaan!", + "ManageYourAccount": "Hallitse tiliäsi" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json index 8084270436..c27708ee09 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json @@ -46,6 +46,7 @@ "GoBack": "Retour", "Search": "Recherche", "ItemWillBeDeletedMessageWithFormat": "{0} sera supprimé!", - "ItemWillBeDeletedMessage": "Cet objet va être supprimé!" + "ItemWillBeDeletedMessage": "Cet objet va être supprimé!", + "ManageYourAccount": "Gérer votre compte" } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json new file mode 100644 index 0000000000..7fbdb1375a --- /dev/null +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json @@ -0,0 +1,52 @@ +{ + "culture": "hi", + "texts": { + "Languages": "बोली", + "AreYouSure": "क्या आपको यकीन है?", + "Cancel": "रद्द करना", + "Clear": "स्पष्ट", + "Yes": "हाँ", + "No": "नहीं न", + "Ok": "ठीक है", + "Close": "बंद करे", + "Save": "सहेजें", + "SavingWithThreeDot": "सहेजा जा रहा है ...", + "Actions": "कार्रवाई", + "Delete": "हटाएं", + "Edit": "संपादित करें", + "Refresh": "ताज़ा करना", + "Language": "भाषा: हिन्दी", + "LoadMore": "और लोड करें", + "ProcessingWithThreeDot": "प्रसंस्करण ...", + "LoadingWithThreeDot": "लोड हो रहा है...", + "Welcome": "स्वागत हे", + "Login": "लॉग इन करें", + "Register": "रजिस्टर करें", + "Logout": "लॉग आउट", + "Submit": "प्रस्तुत", + "Back": "वापस", + "PagerSearch": "खोज", + "PagerNext": "अगला", + "PagerPrevious": "पहले का", + "PagerFirst": "प्रथम", + "PagerLast": "पिछले", + "PagerInfo": "_TARTAL_ प्रविष्टियों में से _START_ से _END_ दिखा रहा है", + "PagerInfo{0}{1}{2}": "{2} प्रविष्टियों में {0} से {1} दिखा रहा है", + "PagerInfoEmpty": "0 से 0 प्रविष्टियों को दिखा रहा है", + "PagerInfoFiltered": "(_MAX_ कुल प्रविष्टियों से फ़िल्टर किया गया)", + "NoDataAvailableInDatatable": "कोई डेटा उपलब्ध नहीं है", + "Total": "संपूर्ण", + "Selected": "चयनित", + "PagerShowMenuEntries": "_MENU_ प्रविष्टियाँ दिखाएँ", + "DatatableActionDropdownDefaultText": "कार्रवाई", + "ChangePassword": "पासवर्ड बदलें", + "PersonalInfo": "मेरी प्रोफाइल", + "AreYouSureYouWantToCancelEditingWarningMessage": "आपके पास सहेजे नहीं गए परिवर्तन हैं।", + "GoHomePage": "होम पेज़ पर जाएं", + "GoBack": "वापस जाओ", + "Search": "खोज", + "ItemWillBeDeletedMessageWithFormat": "{0} हटा दिया जाएगा!", + "ItemWillBeDeletedMessage": "यह आइटम हटा दिया जाएगा!", + "ManageYourAccount": "अपने खाते का प्रबंधन" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json new file mode 100644 index 0000000000..6a66828c6e --- /dev/null +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json @@ -0,0 +1,52 @@ +{ + "culture": "it", + "texts": { + "Languages": "Le lingue", + "AreYouSure": "Sei sicuro?", + "Cancel": "Annulla", + "Clear": "Chiaro", + "Yes": "sì", + "No": "No", + "Ok": "Ok", + "Close": "Vicino", + "Save": "Salva", + "SavingWithThreeDot": "Salvataggio...", + "Actions": "Azioni", + "Delete": "Elimina", + "Edit": "modificare", + "Refresh": "ricaricare", + "Language": "linguaggio", + "LoadMore": "Carica di più", + "ProcessingWithThreeDot": "In lavorazione...", + "LoadingWithThreeDot": "Caricamento in corso...", + "Welcome": "benvenuto", + "Login": "Login", + "Register": "Registrati", + "Logout": "Disconnettersi", + "Submit": "Invia", + "Back": "Indietro", + "PagerSearch": "Ricerca", + "PagerNext": "Il prossimo", + "PagerPrevious": "Precedente", + "PagerFirst": "Primo", + "PagerLast": "Scorso", + "PagerInfo": "Visualizzazione da _START_ a _END_ di _TOTAL_ voci", + "PagerInfo{0}{1}{2}": "Visualizzazione da {0} a {1} di {2} voci", + "PagerInfoEmpty": "Mostra da 0 a 0 di 0 voci", + "PagerInfoFiltered": "(filtrato da _MAX_ voci totali)", + "NoDataAvailableInDatatable": "Nessun dato disponibile", + "Total": "totale", + "Selected": "selezionato", + "PagerShowMenuEntries": "Mostra voci _MENU_", + "DatatableActionDropdownDefaultText": "Azioni", + "ChangePassword": "Cambia la password", + "PersonalInfo": "Il mio profilo", + "AreYouSureYouWantToCancelEditingWarningMessage": "Hai modifiche non salvate.", + "GoHomePage": "Vai alla home page", + "GoBack": "Torna indietro", + "Search": "Ricerca", + "ItemWillBeDeletedMessageWithFormat": "{0} verrà eliminato!", + "ItemWillBeDeletedMessage": "Questo articolo sarà eliminato!", + "ManageYourAccount": "Gestire il tuo account" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json index 69ad662be1..a85e443bdf 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json @@ -7,7 +7,7 @@ "Clear": "Wissen", "Yes": "Ja", "No": "Nee", - "Ok": "Ok", + "Ok": "Oké", "Close": "Sluiten", "Save": "Opslaan", "SavingWithThreeDot": "Opslaan...", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json index 59a680bb81..96c49401ea 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json @@ -4,7 +4,7 @@ "Languages": "语言", "AreYouSure": "你确定吗?", "Cancel": "取消", - "Clear": "清楚", + "Clear": "清除", "Yes": "是", "No": "否", "Ok": "Ok", @@ -49,4 +49,4 @@ "ItemWillBeDeletedMessage": "此项将被删除!", "ManageYourAccount": "管理你的账户" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/fi.json b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/fi.json new file mode 100644 index 0000000000..f4501b87cf --- /dev/null +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/fi.json @@ -0,0 +1,34 @@ +{ + "culture": "fi", + "texts": { + "'{0}' and '{1}' do not match.": "{0} ja {1} eivät täsmää.", + "The {0} field is not a valid credit card number.": "Kenttä {0} ei ole kelvollinen luottokortin numero.", + "{0} is not valid.": "{0} ei kelpaa.", + "The {0} field is not a valid e-mail address.": "{0} -kenttä ei ole kelvollinen sähköpostiosoite.", + "The {0} field only accepts files with the following extensions: {1}": "{0} -kenttä hyväksyy vain tiedostot, joilla on seuraavat laajennukset: {1}", + "The field {0} must be a string or array type with a maximum length of '{1}'.": "Kentän {0} on oltava merkkijono- tai taulukotyyppi, jonka enimmäispituus on {1}.", + "The field {0} must be a string or array type with a minimum length of '{1}'.": "Kentän {0} on oltava merkkijono tai matriisityyppi, jonka vähimmäispituus on {1}.", + "The {0} field is not a valid phone number.": "{0} -kenttä ei ole kelvollinen puhelinnumero.", + "The field {0} must be between {1} and {2}.": "Kentän {0} on oltava välillä {1} - {2}.", + "The field {0} must match the regular expression '{1}'.": "Kenttä {0} ei vastaa pyydettyä muotoa.", + "The {0} field is required.": "{0} -kenttä on pakollinen.", + "The field {0} must be a string with a maximum length of {1}.": "Kentän {0} on oltava merkkijono, jonka enimmäispituus on {1}.", + "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "Kentän {0} on oltava merkkijono, jonka vähimmäispituus on {2} ja enimmäispituus {1}.", + "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "{0} -kenttä ei ole kelvollinen täysin hyväksytty http, https tai ftp URL.", + "The field {0} is invalid.": "Kenttä {0} on virheellinen.", + "ThisFieldIsNotAValidCreditCardNumber.": "Tämä kenttä ei ole kelvollinen luottokortin numero.", + "ThisFieldIsNotValid.": "Tämä kenttä ei kelpaa.", + "ThisFieldIsNotAValidEmailAddress.": "Tämä kenttä ei ole kelvollinen sähköpostiosoite.", + "ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions:{0}": "Tämä kenttä hyväksyy vain tiedostot, joilla on seuraavat laajennukset: {0}", + "ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}": "Tämän kentän on oltava merkkijono- tai taulukotyyppi, jonka enimmäispituus on {0}.", + "ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "Tämän kentän on oltava merkkijono- tai taulukotyyppi, jonka vähimmäispituus on {0}.", + "ThisFieldIsNotAValidPhoneNumber.": "Tämä kenttä ei ole kelvollinen puhelinnumero.", + "ThisFieldMustBeBetween{0}And{1}": "Tämän kentän on oltava välillä {0} - {1}.", + "ThisFieldMustMatchTheRegularExpression{0}": "Tämän kentän on vastattava säännöllistä lauseketta {0}.", + "ThisFieldIsRequired.": "Tämä kenttä pitää täyttää.", + "ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "Tämän kentän on oltava merkkijono, jonka enimmäispituus on {0}.", + "ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}": "Tämän kentän on oltava merkkijono, jonka vähimmäispituus on {1} ja enimmäispituus {0}.", + "ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl": "Tämä kenttä ei ole kelvollinen täysin hyväksytty http, https tai ftp URL.", + "ThisFieldIsInvalid.": "Tämä kenttä on virheellinen." + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/hi.json b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/hi.json new file mode 100644 index 0000000000..fab1a394b4 --- /dev/null +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/hi.json @@ -0,0 +1,34 @@ +{ + "culture": "hi", + "texts": { + "'{0}' and '{1}' do not match.": "'{0}' और '{1}' मेल नहीं खाते।", + "The {0} field is not a valid credit card number.": "{0} फ़ील्ड मान्य क्रेडिट कार्ड नंबर नहीं है।", + "{0} is not valid.": "{0} मान्य नहीं है।", + "The {0} field is not a valid e-mail address.": "{0} फ़ील्ड मान्य ई-मेल पता नहीं है।", + "The {0} field only accepts files with the following extensions: {1}": "{0} फ़ील्ड केवल निम्नलिखित एक्सटेंशन वाली फाइलें स्वीकार करती है: {1}", + "The field {0} must be a string or array type with a maximum length of '{1}'.": "फ़ील्ड {0} एक स्ट्रिंग या सरणी प्रकार होना चाहिए जिसकी अधिकतम लंबाई '{1}' हो।", + "The field {0} must be a string or array type with a minimum length of '{1}'.": "फ़ील्ड {0} में '{1}' की न्यूनतम लंबाई के साथ एक स्ट्रिंग या सरणी प्रकार होना चाहिए।", + "The {0} field is not a valid phone number.": "{0} फ़ील्ड एक मान्य फ़ोन नंबर नहीं है।", + "The field {0} must be between {1} and {2}.": "फ़ील्ड {0} को {1} और {2} के बीच होना चाहिए।", + "The field {0} must match the regular expression '{1}'.": "फ़ील्ड {0} अनुरोधित प्रारूप से मेल नहीं खाती है।", + "The {0} field is required.": "{0} फ़ील्ड आवश्यक है।", + "The field {0} must be a string with a maximum length of {1}.": "फ़ील्ड {0} की लंबाई अधिकतम लंबाई के साथ होनी चाहिए {1}।", + "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "फ़ील्ड {0} की लंबाई न्यूनतम {2} और अधिकतम लंबाई {1} होनी चाहिए।", + "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "{0} फ़ील्ड मान्य पूर्णत: योग्य http, https, या ftp URL नहीं है।", + "The field {0} is invalid.": "फ़ील्ड {0} अमान्य है।", + "ThisFieldIsNotAValidCreditCardNumber.": "यह फ़ील्ड मान्य क्रेडिट कार्ड नंबर नहीं है।", + "ThisFieldIsNotValid.": "यह फ़ील्ड मान्य नहीं है।", + "ThisFieldIsNotAValidEmailAddress.": "यह फ़ील्ड मान्य ई-मेल पता नहीं है।", + "ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions:{0}": "यह फ़ील्ड केवल निम्नलिखित एक्सटेंशन वाली फाइलें स्वीकार करती है: {0}", + "ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}": "यह फ़ील्ड '{0}' की अधिकतम लंबाई के साथ एक स्ट्रिंग या सरणी प्रकार होना चाहिए।", + "ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "यह फ़ील्ड '{0}' की न्यूनतम लंबाई के साथ एक स्ट्रिंग या सरणी प्रकार होनी चाहिए।", + "ThisFieldIsNotAValidPhoneNumber.": "यह फ़ील्ड मान्य फ़ोन नंबर नहीं है।", + "ThisFieldMustBeBetween{0}And{1}": "यह फ़ील्ड {0} और {1} के बीच होनी चाहिए।", + "ThisFieldMustMatchTheRegularExpression{0}": "यह फ़ील्ड नियमित अभिव्यक्ति '{0}' से मेल खाना चाहिए।", + "ThisFieldIsRequired.": "यह फ़ील्ड आवश्यक है।", + "ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "यह फ़ील्ड {0} की अधिकतम लंबाई के साथ एक स्ट्रिंग होनी चाहिए।", + "ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}": "यह फ़ील्ड न्यूनतम लंबाई {1} और अधिकतम लंबाई {0} के साथ होनी चाहिए।", + "ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl": "यह फ़ील्ड एक पूरी तरह से योग्य http, https, या ftp URL नहीं है।", + "ThisFieldIsInvalid.": "यह फ़ील्ड अमान्य है।" + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/it.json b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/it.json new file mode 100644 index 0000000000..162e186cde --- /dev/null +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/it.json @@ -0,0 +1,34 @@ +{ + "culture": "it", + "texts": { + "'{0}' and '{1}' do not match.": "\"{0}\" e \"{1}\" non corrispondono.", + "The {0} field is not a valid credit card number.": "Il campo {0} non è un numero di carta di credito valido.", + "{0} is not valid.": "{0} non è valido.", + "The {0} field is not a valid e-mail address.": "Il campo {0} non è un indirizzo e-mail valido.", + "The {0} field only accepts files with the following extensions: {1}": "Il campo {0} accetta solo file con le seguenti estensioni: {1}", + "The field {0} must be a string or array type with a maximum length of '{1}'.": "Il campo {0} deve essere una stringa o un tipo di matrice con una lunghezza massima di \"{1}\".", + "The field {0} must be a string or array type with a minimum length of '{1}'.": "Il campo {0} deve essere una stringa o un tipo di matrice con una lunghezza minima di \"{1}\".", + "The {0} field is not a valid phone number.": "Il campo {0} non è un numero di telefono valido.", + "The field {0} must be between {1} and {2}.": "Il campo {0} deve essere compreso tra {1} e {2}.", + "The field {0} must match the regular expression '{1}'.": "Il campo {0} non corrisponde al formato richiesto.", + "The {0} field is required.": "Il campo {0} è obbligatorio.", + "The field {0} must be a string with a maximum length of {1}.": "Il campo {0} deve essere una stringa con una lunghezza massima di {1}.", + "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "Il campo {0} deve essere una stringa con una lunghezza minima di {2} e una lunghezza massima di {1}.", + "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "Il campo {0} non è un URL http, https o ftp completo e valido.", + "The field {0} is invalid.": "Il campo {0} non è valido.", + "ThisFieldIsNotAValidCreditCardNumber.": "Questo campo non è un numero di carta di credito valido.", + "ThisFieldIsNotValid.": "Questo campo non è valido.", + "ThisFieldIsNotAValidEmailAddress.": "Questo campo non è un indirizzo e-mail valido.", + "ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions:{0}": "Questo campo accetta solo file con le seguenti estensioni: {0}", + "ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}": "Questo campo deve essere un tipo stringa o matrice con una lunghezza massima di \"{0}\".", + "ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "Questo campo deve essere una stringa o un tipo di matrice con una lunghezza minima di \"{0}\".", + "ThisFieldIsNotAValidPhoneNumber.": "Questo campo non è un numero di telefono valido.", + "ThisFieldMustBeBetween{0}And{1}": "Questo campo deve essere compreso tra {0} e {1}.", + "ThisFieldMustMatchTheRegularExpression{0}": "Questo campo deve corrispondere all'espressione regolare \"{0}\".", + "ThisFieldIsRequired.": "Questo campo è obbligatorio.", + "ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "Questo campo deve essere una stringa con una lunghezza massima di {0}.", + "ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}": "Questo campo deve essere una stringa con una lunghezza minima di {1} e una lunghezza massima di {0}.", + "ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl": "Questo campo non è un URL http, https o ftp completo e valido.", + "ThisFieldIsInvalid.": "Questo campo non è valido." + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/fi.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/fi.json new file mode 100644 index 0000000000..9e0ba9d1ed --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/fi.json @@ -0,0 +1,7 @@ +{ + "culture": "fi", + "texts": { + "BirthDate": "Syntymäpäivä", + "Value1": "Arvo Yksi" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/hi.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/hi.json new file mode 100644 index 0000000000..eccd8f62d7 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/hi.json @@ -0,0 +1,7 @@ +{ + "culture": "hi", + "texts": { + "BirthDate": "जन्म तिथि", + "Value1": "मान एक" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/it.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/it.json new file mode 100644 index 0000000000..954ab19de0 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/it.json @@ -0,0 +1,7 @@ +{ + "culture": "it", + "texts": { + "BirthDate": "Data di nascita", + "Value1": "Valore uno" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/AbpAspNetCoreMvcUiBootstrapDemoTestBase.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/AbpAspNetCoreMvcUiBootstrapDemoTestBase.cs index 15473df986..d7a8a88c2a 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/AbpAspNetCoreMvcUiBootstrapDemoTestBase.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/AbpAspNetCoreMvcUiBootstrapDemoTestBase.cs @@ -18,10 +18,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo { return CalculateContentRootPath( "Volo.Abp.sln", - string.Format( - "test{0}Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo", - Path.DirectorySeparatorChar - ) + $"test{Path.DirectorySeparatorChar}Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo" ); } diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml index 6fa9cabb37..4d60a98ea0 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml @@ -97,7 +97,9 @@
- + + +
@@ -140,7 +142,9 @@

 <abp-input asp-for="@@Model.MyModel.EmailAddress" label="Email Address" placeholder="name@example.com" />
-<abp-select asp-for="@@Model.MyModel.City" asp-items="@@Model.CityList" label="City" />
+<abp-select asp-for="@@Model.MyModel.City" asp-items="@@Model.CityList" label="City">
+    <option value="">Choose a city</option>
+</abp-select>
 <abp-select asp-for="@@Model.MyModel.Cities" asp-items="@@Model.CityList" label="Cities" />
 <abp-input asp-for="@@Model.MyModel.Description" label="Description" />
 
@@ -155,6 +159,7 @@ <div class="form-group"> <label for="MyModel_City">City</label> <select id="MyModel_City" name="MyModel.City" class="form-control"> + <option value="">Choose a city</option> <option value="NY">New York</option> <option value="LDN">London</option> <option value="IST">Istanbul</option> diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Tests/Volo/Abp/AspNetCore/Mvc/UI/Theme/Shared/Toolbars/Toolbar_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Tests/Volo/Abp/AspNetCore/Mvc/UI/Theme/Shared/Toolbars/Toolbar_Tests.cs index 70ca907fac..928a2af8de 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Tests/Volo/Abp/AspNetCore/Mvc/UI/Theme/Shared/Toolbars/Toolbar_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Tests/Volo/Abp/AspNetCore/Mvc/UI/Theme/Shared/Toolbars/Toolbar_Tests.cs @@ -11,6 +11,7 @@ using NSubstitute; using Shouldly; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars; using Volo.Abp.AspNetCore.Mvc.UI.Theming; +using Volo.Abp.Authorization.Permissions; using Volo.Abp.Security.Claims; using Xunit; @@ -71,8 +72,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Tests.Volo.Abp.AspNetCore.Mvc. return Task.CompletedTask; } - context.Toolbar.Items.Add(new ToolbarItem(typeof(MyComponent1), requiredPermissionName: "MyComponent1")); - context.Toolbar.Items.Add(new ToolbarItem(typeof(MyComponent2), requiredPermissionName: "MyComponent2")); + context.Toolbar.Items.Add(new ToolbarItem(typeof(MyComponent1)).RequirePermissions("MyComponent1")); + context.Toolbar.Items.Add(new ToolbarItem(typeof(MyComponent2)).RequirePermissions("MyComponent2")); return Task.CompletedTask; } @@ -87,7 +88,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Tests.Volo.Abp.AspNetCore.Mvc. return Task.CompletedTask; } - context.Toolbar.Items.Add(new ToolbarItem(typeof(MyComponent3), requiredPermissionName: "MyComponent3")); + context.Toolbar.Items.Add(new ToolbarItem(typeof(MyComponent3)).RequirePermissions("MyComponent3")); context.Toolbar.Items.Add(new ToolbarItem(typeof(MyComponent4))); return Task.CompletedTask; diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionStateProvider_Tests.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionStateProvider_Tests.cs index f7ab858ac1..43dfa11330 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionStateProvider_Tests.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/PermissionStateProvider_Tests.cs @@ -5,19 +5,20 @@ using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.Authorization.Permissions; using Volo.Abp.Security.Claims; +using Volo.Abp.SimpleStateChecking; using Xunit; namespace Volo.Abp.Authorization { public abstract class PermissionStateProvider_Tests : AuthorizationTestBase { - protected IPermissionStateManager PermissionStateManager { get; } + protected ISimpleStateCheckerManager StateCheckerManager { get; } protected IPermissionDefinitionManager PermissionDefinitionManager { get; } protected ICurrentPrincipalAccessor CurrentPrincipalAccessor { get; } public PermissionStateProvider_Tests() { - PermissionStateManager = GetRequiredService(); + StateCheckerManager = GetRequiredService>(); PermissionDefinitionManager = GetRequiredService(); CurrentPrincipalAccessor = GetRequiredService(); } @@ -29,13 +30,13 @@ namespace Volo.Abp.Authorization public async Task PermissionState_Test() { var myPermission1 = PermissionDefinitionManager.Get("MyPermission1"); - myPermission1.StateProviders.ShouldContain(x => x.GetType() == typeof(TestRequireEditionPermissionStateProvider)); + myPermission1.StateCheckers.ShouldContain(x => x.GetType() == typeof(TestRequireEditionPermissionSimpleStateChecker)); - (await PermissionStateManager.IsEnabledAsync(myPermission1)).ShouldBeFalse(); + (await StateCheckerManager.IsEnabledAsync(myPermission1)).ShouldBeFalse(); using (CurrentPrincipalAccessor.Change(new Claim(AbpClaimTypes.EditionId, Guid.NewGuid().ToString()))) { - (await PermissionStateManager.IsEnabledAsync(myPermission1)).ShouldBeTrue(); + (await StateCheckerManager.IsEnabledAsync(myPermission1)).ShouldBeTrue(); } } } @@ -44,7 +45,10 @@ namespace Volo.Abp.Authorization { protected override void AfterAddApplication(IServiceCollection services) { - services.Configure(options => options.GlobalStateProviders.Add()); + services.Configure>(options => + { + options.GlobalStateCheckers.Add(); + }); } [Fact] @@ -52,11 +56,11 @@ namespace Volo.Abp.Authorization { var myPermission2 = PermissionDefinitionManager.Get("MyPermission2"); - (await PermissionStateManager.IsEnabledAsync(myPermission2)).ShouldBeFalse(); + (await StateCheckerManager.IsEnabledAsync(myPermission2)).ShouldBeFalse(); using (CurrentPrincipalAccessor.Change(new Claim(AbpClaimTypes.Role, "admin"))) { - (await PermissionStateManager.IsEnabledAsync(myPermission2)).ShouldBeTrue(); + (await StateCheckerManager.IsEnabledAsync(myPermission2)).ShouldBeTrue(); } } } diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/RequirePermissionsSimpleBatchStateChecker_Tests.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/RequirePermissionsSimpleBatchStateChecker_Tests.cs new file mode 100644 index 0000000000..a3b7a96eea --- /dev/null +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/RequirePermissionsSimpleBatchStateChecker_Tests.cs @@ -0,0 +1,79 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.SimpleStateChecking; +using Xunit; + +namespace Volo.Abp.Authorization +{ + public class RequirePermissionsSimpleBatchStateChecker_Tests : AuthorizationTestBase + { + private readonly ISimpleStateCheckerManager _simpleStateCheckerManager; + + public RequirePermissionsSimpleBatchStateChecker_Tests() + { + _simpleStateCheckerManager = GetRequiredService>(); + } + + [Fact] + public void Switch_Current_Checker_Test() + { + var checker = RequirePermissionsSimpleBatchStateChecker.Current; + checker.ShouldNotBeNull(); + + RequirePermissionsSimpleBatchStateChecker checker2 = null; + + using (RequirePermissionsSimpleBatchStateChecker.Use(new RequirePermissionsSimpleBatchStateChecker())) + { + checker2 = RequirePermissionsSimpleBatchStateChecker.Current; + checker2.ShouldNotBeNull(); + checker2.ShouldNotBe(checker); + } + + checker2.ShouldNotBeNull(); + checker2.ShouldNotBe(checker); + } + + [Fact] + public async Task RequirePermissionsSimpleBatchStateChecker_Test() + { + var myStateEntities = new MyStateEntity[] + { + new MyStateEntity().RequirePermissions(requiresAll: true, batchCheck:true, permissions: "MyPermission3"), + new MyStateEntity().RequirePermissions(requiresAll: true, batchCheck:true, permissions: "MyPermission4"), + new MyStateEntity().RequirePermissions(requiresAll: true, batchCheck:true, permissions: "MyPermission4"), + new MyStateEntity().RequirePermissions(requiresAll: true, batchCheck:true, permissions: "MyPermission5"), + }; + + var result = await _simpleStateCheckerManager.IsEnabledAsync(myStateEntities); + + result.Count.ShouldBe(myStateEntities.Length); + + result[myStateEntities[0]].ShouldBeTrue(); + result[myStateEntities[1]].ShouldBeFalse(); + result[myStateEntities[2]].ShouldBeFalse(); + result[myStateEntities[3]].ShouldBeTrue(); + } + + class MyStateEntity : IHasSimpleStateCheckers + { + public List> StateCheckers { get; } + + public MyStateEntity() + { + StateCheckers = new List>(); + } + } + + class MyStateEntity2 : IHasSimpleStateCheckers + { + public List> StateCheckers { get; } + + public MyStateEntity2() + { + StateCheckers = new List>(); + } + } + } +} diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestGlobalRequireRolePermissionStateProvider.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestGlobalRequireRolePermissionSimpleStateChecker.cs similarity index 65% rename from framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestGlobalRequireRolePermissionStateProvider.cs rename to framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestGlobalRequireRolePermissionSimpleStateChecker.cs index 6e3b58d2de..78726a343d 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestGlobalRequireRolePermissionStateProvider.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestGlobalRequireRolePermissionSimpleStateChecker.cs @@ -3,12 +3,13 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Authorization.Permissions; using Volo.Abp.DependencyInjection; using Volo.Abp.Security.Claims; +using Volo.Abp.SimpleStateChecking; namespace Volo.Abp.Authorization { - public class TestGlobalRequireRolePermissionStateProvider : IPermissionStateProvider, ITransientDependency + public class TestGlobalRequireRolePermissionSimpleStateChecker : ISimpleStateChecker, ITransientDependency { - public Task IsEnabledAsync(PermissionStateContext context) + public Task IsEnabledAsync(SimpleStateCheckerContext context) { var currentPrincipalAccessor = context.ServiceProvider.GetRequiredService(); return Task.FromResult(currentPrincipalAccessor.Principal != null && currentPrincipalAccessor.Principal.IsInRole("admin")); diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestRequireEditionPermissionStateProvider.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestRequireEditionPermissionSimpleStateChecker.cs similarity index 66% rename from framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestRequireEditionPermissionStateProvider.cs rename to framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestRequireEditionPermissionSimpleStateChecker.cs index a793c84431..8ce5ab9523 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestRequireEditionPermissionStateProvider.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestRequireEditionPermissionSimpleStateChecker.cs @@ -3,12 +3,13 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Authorization.Permissions; using Volo.Abp.Security.Claims; +using Volo.Abp.SimpleStateChecking; namespace Volo.Abp.Authorization { - public class TestRequireEditionPermissionStateProvider : IPermissionStateProvider + public class TestRequireEditionPermissionSimpleStateChecker : ISimpleStateChecker { - public Task IsEnabledAsync(PermissionStateContext context) + public Task IsEnabledAsync(SimpleStateCheckerContext context) { var currentPrincipalAccessor = context.ServiceProvider.GetRequiredService(); return Task.FromResult(currentPrincipalAccessor.Principal?.FindEditionId() != null); diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/AuthorizationTestPermissionDefinitionProvider.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/AuthorizationTestPermissionDefinitionProvider.cs index d67cf8febc..2f78069e96 100644 --- a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/AuthorizationTestPermissionDefinitionProvider.cs +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/AuthorizationTestPermissionDefinitionProvider.cs @@ -17,8 +17,11 @@ namespace Volo.Abp.Authorization.TestServices group.AddPermission("MyAuthorizedService1"); - group.AddPermission("MyPermission1").AddStateProviders(new TestRequireEditionPermissionStateProvider()); + group.AddPermission("MyPermission1").StateCheckers.Add(new TestRequireEditionPermissionSimpleStateChecker()); group.AddPermission("MyPermission2"); + group.AddPermission("MyPermission3"); + group.AddPermission("MyPermission4"); + group.AddPermission("MyPermission5"); group.GetPermissionOrNull("MyAuthorizedService1").ShouldNotBeNull(); diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/FakePermissionStore.cs b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/FakePermissionStore.cs new file mode 100644 index 0000000000..56446bcd26 --- /dev/null +++ b/framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/FakePermissionStore.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Authorization.TestServices +{ + public class FakePermissionStore : IPermissionStore, ITransientDependency + { + public Task IsGrantedAsync(string name, string providerName, string providerKey) + { + return Task.FromResult(name == "MyPermission3" || name == "MyPermission5"); + } + + public Task IsGrantedAsync(string[] names, string providerName, string providerKey) + { + var result = new MultiplePermissionGrantResult(); + foreach (var name in names) + { + result.Result.Add(name, name == "MyPermission3" || name == "MyPermission5" + ? PermissionGrantResult.Granted + : PermissionGrantResult.Prohibited); + } + + return Task.FromResult(result); + } + } +} diff --git a/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/CommandLineArgumentParser_Tests.cs b/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/CommandLineArgumentParser_Tests.cs index c8d31990cf..36174f1004 100644 --- a/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/CommandLineArgumentParser_Tests.cs +++ b/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/CommandLineArgumentParser_Tests.cs @@ -64,5 +64,26 @@ namespace Volo.Abp.Cli commandLineArgs.Options.ShouldContainKey("optionC"); commandLineArgs.Options["optionC"].ShouldBe("value2"); } + + [Fact] + public void Should_Parse_From_Line_Text() + { + var commandLineArgs = _commandLineArgumentParser.Parse( + "mycommand mytarget -a value1 -b \"value with space\" --optionC" + ); + + commandLineArgs.Command.ShouldBe("mycommand"); + commandLineArgs.Target.ShouldBe("mytarget"); + commandLineArgs.Options.Any().ShouldBeTrue(); + + commandLineArgs.Options.ShouldContainKey("a"); + commandLineArgs.Options["a"].ShouldBe("value1"); + + commandLineArgs.Options.ShouldContainKey("b"); + commandLineArgs.Options["b"].ShouldBe("value with space"); + + commandLineArgs.Options.ShouldContainKey("optionC"); + commandLineArgs.Options["optionC"].ShouldBeNull(); + } } } diff --git a/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/ProjectNameValidation_Tests.cs b/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/ProjectNameValidation_Tests.cs new file mode 100644 index 0000000000..cd8581f912 --- /dev/null +++ b/framework/test/Volo.Abp.Cli.Core.Tests/Volo/Abp/Cli/ProjectNameValidation_Tests.cs @@ -0,0 +1,49 @@ +using System.IO; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Commands; +using Volo.Abp.Cli.ProjectModification; +using Xunit; + +namespace Volo.Abp.Cli +{ + public class ProjectNameValidation_Tests : AbpCliTestBase + { + private readonly NewCommand _newCommand; + + public ProjectNameValidation_Tests() + { + _newCommand = GetRequiredService(); + } + + [Fact] + public async Task IllegalProjectName_Test() + { + var illegalProjectNames = new[] + { + "MyCompanyName.MyProjectName", + "MyProjectName", + "CON", //Windows doesn't accept these names as file name + "AUX", + "PRN", + "COM1", + "LPT2" + }; + + foreach (var illegalProjectName in illegalProjectNames) + { + var args = new CommandLineArgs("new", illegalProjectName); + await _newCommand.ExecuteAsync(args).ShouldThrowAsync(); + } + } + + [Fact] + public async Task ParentDirectoryContain_Test() + { + + var args = new CommandLineArgs("new", "Test..Test"); + await _newCommand.ExecuteAsync(args).ShouldThrowAsync(); + } + } +} diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/AbpTestModule.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/AbpTestModule.cs new file mode 100644 index 0000000000..b42ff1e6e8 --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/AbpTestModule.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Modularity; + +namespace Volo.Abp +{ + public class AbpTestModule : AbpModule + { + + } +} diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateCheckerTestBase.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateCheckerTestBase.cs new file mode 100644 index 0000000000..2debf8a66b --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateCheckerTestBase.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Testing; + +namespace Volo.Abp.SimpleStateChecking +{ + public abstract class SimpleStateCheckerTestBase : AbpIntegratedTest + { + protected readonly ISimpleStateCheckerManager SimpleStateCheckerManager; + + public SimpleStateCheckerTestBase() + { + SimpleStateCheckerManager = GetRequiredService>(); + } + + public class MyStateEntity : IHasSimpleStateCheckers + { + public int CheckCount { get; set; } + + public int GlobalCheckCount { get; set; } + + public int MultipleCheckCount { get; set; } + + public int MultipleGlobalCheckCount { get; set; } + + public DateTime CreationTime { get; set; } + + public DateTime? LastModificationTime { get; set; } + + public List> StateCheckers { get; } + + public MyStateEntity() + { + StateCheckers = new List>(); + } + + public MyStateEntity AddSimpleStateChecker(ISimpleStateChecker checker) + { + StateCheckers.Add(checker); + return this; + } + } + + public class MySimpleStateChecker : ISimpleStateChecker + { + public Task IsEnabledAsync(SimpleStateCheckerContext context) + { + context.State.CheckCount += 1; + return Task.FromResult(context.State.CreationTime > DateTime.Parse("2020-01-01", CultureInfo.InvariantCulture)); + } + } + + public class MyGlobalSimpleStateChecker : ISimpleStateChecker, ITransientDependency + { + public Task IsEnabledAsync(SimpleStateCheckerContext context) + { + context.State.GlobalCheckCount += 1; + return Task.FromResult(context.State.LastModificationTime.HasValue); + } + } + + public class MySimpleBatchStateChecker : SimpleBatchStateCheckerBase + { + public override Task> IsEnabledAsync(SimpleBatchStateCheckerContext context) + { + foreach (var state in context.States) + { + state.MultipleCheckCount += 1; + } + + var result = new SimpleStateCheckerResult(context.States); + + foreach (var x in result) + { + result[x.Key] = x.Key.CreationTime > DateTime.Parse("2020-01-01", CultureInfo.InvariantCulture); + } + + return Task.FromResult(result); + } + } + + public class MyGlobalSimpleBatchStateChecker : SimpleBatchStateCheckerBase, ITransientDependency + { + public override Task> IsEnabledAsync(SimpleBatchStateCheckerContext context) + { + foreach (var state in context.States) + { + state.MultipleGlobalCheckCount += 1; + } + + var result = new SimpleStateCheckerResult(context.States); + + foreach (var x in result) + { + result[x.Key] = x.Key.LastModificationTime.HasValue; + } + + return Task.FromResult(result); + } + } + } +} diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateChecker_CheckCount_Test.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateChecker_CheckCount_Test.cs new file mode 100644 index 0000000000..ff7f320bb3 --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateChecker_CheckCount_Test.cs @@ -0,0 +1,81 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.SimpleStateChecking +{ + public class SimpleStateChecker_CheckCount_Test : SimpleStateCheckerTestBase + { + [Fact] + public async Task Simple_State_Check_Should_Be_Prevent_Multiple_Checks() + { + var myStateEntities = new SimpleStateCheckerTestBase.MyStateEntity[] + { + new SimpleStateCheckerTestBase.MyStateEntity() + { + CreationTime = DateTime.Parse("2022-01-01", CultureInfo.InvariantCulture) + }, + + new SimpleStateCheckerTestBase.MyStateEntity() + { + CreationTime = DateTime.Parse("2020-01-01", CultureInfo.InvariantCulture), + } + }; + + myStateEntities[0].AddSimpleStateChecker(new MySimpleBatchStateChecker()); + myStateEntities[1].AddSimpleStateChecker(new MySimpleStateChecker()); + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntities[0])).ShouldBeTrue(); + + myStateEntities[0].CheckCount.ShouldBe(0); + myStateEntities[0].GlobalCheckCount.ShouldBe(0); + myStateEntities[0].MultipleCheckCount.ShouldBe(1); + myStateEntities[0].MultipleGlobalCheckCount.ShouldBe(0); + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntities[1])).ShouldBeFalse(); + + myStateEntities[1].CheckCount.ShouldBe(1); + myStateEntities[1].GlobalCheckCount.ShouldBe(0); + myStateEntities[1].MultipleCheckCount.ShouldBe(0); + myStateEntities[1].MultipleGlobalCheckCount.ShouldBe(0); + } + + [Fact] + public async Task Multiple_And_Simple_State_Check_Should_Be_Prevent_Multiple_Checks() + { + var myStateEntities = new SimpleStateCheckerTestBase.MyStateEntity[] + { + new SimpleStateCheckerTestBase.MyStateEntity() + { + CreationTime = DateTime.Parse("2022-01-01", CultureInfo.InvariantCulture) + }, + + new SimpleStateCheckerTestBase.MyStateEntity() + { + CreationTime = DateTime.Parse("2020-01-01", CultureInfo.InvariantCulture), + } + }; + + myStateEntities[0].AddSimpleStateChecker(new MySimpleBatchStateChecker()); + myStateEntities[1].AddSimpleStateChecker(new MySimpleStateChecker()); + + var result = await SimpleStateCheckerManager.IsEnabledAsync(myStateEntities); + result.Count.ShouldBe(2); + + result[myStateEntities[0]].ShouldBeTrue(); + result[myStateEntities[1]].ShouldBeFalse(); + + myStateEntities[0].CheckCount.ShouldBe(0); + myStateEntities[0].GlobalCheckCount.ShouldBe(0); + myStateEntities[0].MultipleCheckCount.ShouldBe(1); + myStateEntities[0].MultipleGlobalCheckCount.ShouldBe(0); + + myStateEntities[1].CheckCount.ShouldBe(1); + myStateEntities[1].GlobalCheckCount.ShouldBe(0); + myStateEntities[1].MultipleCheckCount.ShouldBe(0); + myStateEntities[1].MultipleGlobalCheckCount.ShouldBe(0); + } + } +} diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateChecker_GlobalCheckCount_Test.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateChecker_GlobalCheckCount_Test.cs new file mode 100644 index 0000000000..c727238139 --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateChecker_GlobalCheckCount_Test.cs @@ -0,0 +1,95 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Xunit; + +namespace Volo.Abp.SimpleStateChecking +{ + public class SimpleStateChecker_GlobalCheckCount_Test : SimpleStateCheckerTestBase + { + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure>(options => + { + options.GlobalStateCheckers.Add(); + options.GlobalStateCheckers.Add(); + }); + + base.AfterAddApplication(services); + } + + [Fact] + public async Task Simple_State_Check_Should_Be_Prevent_Multiple_Checks() + { + var myStateEntities = new SimpleStateCheckerTestBase.MyStateEntity[] + { + new SimpleStateCheckerTestBase.MyStateEntity() + { + CreationTime = DateTime.Parse("2022-01-01", CultureInfo.InvariantCulture), + LastModificationTime = DateTime.Parse("2022-01-01", CultureInfo.InvariantCulture) + }, + + new SimpleStateCheckerTestBase.MyStateEntity() + { + CreationTime = DateTime.Parse("2020-01-01", CultureInfo.InvariantCulture) + } + }; + + myStateEntities[0].AddSimpleStateChecker(new MySimpleBatchStateChecker()); + myStateEntities[1].AddSimpleStateChecker(new MySimpleStateChecker()); + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntities[0])).ShouldBeTrue(); + + myStateEntities[0].CheckCount.ShouldBe(0); + myStateEntities[0].GlobalCheckCount.ShouldBe(1); + myStateEntities[0].MultipleCheckCount.ShouldBe(1); + myStateEntities[0].MultipleGlobalCheckCount.ShouldBe(1); + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntities[1])).ShouldBeFalse(); + + myStateEntities[1].CheckCount.ShouldBe(1); + myStateEntities[1].GlobalCheckCount.ShouldBe(0); + myStateEntities[1].MultipleCheckCount.ShouldBe(0); + myStateEntities[1].MultipleGlobalCheckCount.ShouldBe(0); + } + + [Fact] + public async Task Multiple_And_Simple_State_Check_Should_Be_Prevent_Multiple_Checks() + { + var myStateEntities = new SimpleStateCheckerTestBase.MyStateEntity[] + { + new SimpleStateCheckerTestBase.MyStateEntity() + { + CreationTime = DateTime.Parse("2022-01-01", CultureInfo.InvariantCulture), + LastModificationTime = DateTime.Parse("2022-01-01", CultureInfo.InvariantCulture) + }, + + new SimpleStateCheckerTestBase.MyStateEntity() + { + CreationTime = DateTime.Parse("2020-01-01", CultureInfo.InvariantCulture) + } + }; + + myStateEntities[0].AddSimpleStateChecker(new MySimpleBatchStateChecker()); + myStateEntities[1].AddSimpleStateChecker(new MySimpleStateChecker()); + + var result = await SimpleStateCheckerManager.IsEnabledAsync(myStateEntities); + result.Count.ShouldBe(2); + + result[myStateEntities[0]].ShouldBeTrue(); + result[myStateEntities[1]].ShouldBeFalse(); + + myStateEntities[0].CheckCount.ShouldBe(0); + myStateEntities[0].GlobalCheckCount.ShouldBe(1); + myStateEntities[0].MultipleCheckCount.ShouldBe(1); + myStateEntities[0].MultipleGlobalCheckCount.ShouldBe(1); + + myStateEntities[1].CheckCount.ShouldBe(0); + myStateEntities[1].GlobalCheckCount.ShouldBe(0); + myStateEntities[1].MultipleCheckCount.ShouldBe(0); + myStateEntities[1].MultipleGlobalCheckCount.ShouldBe(1); + } + } +} diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateChecker_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateChecker_Tests.cs new file mode 100644 index 0000000000..06b7cf2eb7 --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/SimpleStateChecking/SimpleStateChecker_Tests.cs @@ -0,0 +1,105 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Xunit; + +namespace Volo.Abp.SimpleStateChecking +{ + public class SimpleStateChecker_Tests : SimpleStateCheckerTestBase + { + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure>(options => + { + options.GlobalStateCheckers.Add(); + options.GlobalStateCheckers.Add(); + }); + + base.AfterAddApplication(services); + } + + [Fact] + public async Task State_Check_Should_Be_Works() + { + var myStateEntity = new MyStateEntity() + { + CreationTime = DateTime.Parse("2021-01-01", CultureInfo.InvariantCulture), + LastModificationTime = DateTime.Parse("2021-01-01", CultureInfo.InvariantCulture) + }; + myStateEntity.AddSimpleStateChecker(new MySimpleStateChecker()); + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntity)).ShouldBeTrue(); + + myStateEntity.CreationTime = DateTime.Parse("2001-01-01", CultureInfo.InvariantCulture); + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntity)).ShouldBeFalse(); + } + + [Fact] + public async Task Global_State_Check_Should_Be_Works() + { + var myStateEntity = new MyStateEntity() + { + CreationTime = DateTime.Parse("2021-01-01", CultureInfo.InvariantCulture) + }; + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntity)).ShouldBeFalse(); + + myStateEntity.LastModificationTime = DateTime.Parse("2001-01-01", CultureInfo.InvariantCulture); + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntity)).ShouldBeTrue(); + } + + [Fact] + public async Task Multiple_State_Check_Should_Be_Works() + { + var checker = new MySimpleBatchStateChecker(); + + var myStateEntities = new MyStateEntity[] + { + new MyStateEntity() + { + CreationTime = DateTime.Parse("2021-01-01", CultureInfo.InvariantCulture), + LastModificationTime = DateTime.Parse("2021-01-01", CultureInfo.InvariantCulture) + }, + + new MyStateEntity() + { + CreationTime = DateTime.Parse("2021-01-01", CultureInfo.InvariantCulture), + LastModificationTime = DateTime.Parse("2021-01-01", CultureInfo.InvariantCulture) + } + }; + + foreach (var myStateEntity in myStateEntities) + { + myStateEntity.AddSimpleStateChecker(checker); + } + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntities)).ShouldAllBe(x => x.Value); + + foreach (var myStateEntity in myStateEntities) + { + myStateEntity.CreationTime = DateTime.Parse("2001-01-01", CultureInfo.InvariantCulture); + } + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntities)).ShouldAllBe(x => !x.Value); + } + + [Fact] + public async Task Multiple_Global_State_Check_Should_Be_Works() + { + var myStateEntity = new MyStateEntity() + { + CreationTime = DateTime.Parse("2021-01-01", CultureInfo.InvariantCulture) + }; + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntity)).ShouldBeFalse(); + + myStateEntity.LastModificationTime = DateTime.Parse("2001-01-01", CultureInfo.InvariantCulture); + + (await SimpleStateCheckerManager.IsEnabledAsync(myStateEntity)).ShouldBeTrue(); + } + } +} diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/fi.json b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/fi.json new file mode 100644 index 0000000000..5c1c8eac8d --- /dev/null +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/fi.json @@ -0,0 +1,6 @@ +{ + "culture": "fi", + "texts": { + "hello": "Hei" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/hi.json b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/hi.json new file mode 100644 index 0000000000..b9f4f11504 --- /dev/null +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/hi.json @@ -0,0 +1,6 @@ +{ + "culture": "hi", + "texts": { + "hello": "नमस्ते" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/it.json b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/it.json new file mode 100644 index 0000000000..30356ca55c --- /dev/null +++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/it.json @@ -0,0 +1,6 @@ +{ + "culture": "it", + "texts": { + "hello": "Ciao" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContext.cs new file mode 100644 index 0000000000..5fa8a80367 --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContext.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext; + +namespace Volo.Abp.EntityFrameworkCore.TestApp.FourthContext +{ + /* This dbcontext is just for testing to replace dbcontext from the application using ReplaceDbContextAttribute + */ + public class FourthDbContext : AbpDbContext, IFourthDbContext + { + public DbSet FourthDummyEntities { get; set; } + + public FourthDbContext(DbContextOptions options) + : base(options) + { + } + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContextDummyEntity.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContextDummyEntity.cs new file mode 100644 index 0000000000..8043301215 --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContextDummyEntity.cs @@ -0,0 +1,10 @@ +using System; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.EntityFrameworkCore.TestApp.FourthContext +{ + public class FourthDbContextDummyEntity : AggregateRoot + { + public string Value { get; set; } + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/IFourthDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/IFourthDbContext.cs new file mode 100644 index 0000000000..eb2380d681 --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/IFourthDbContext.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +namespace Volo.Abp.EntityFrameworkCore.TestApp.FourthContext +{ + public interface IFourthDbContext : IEfCoreDbContext + { + DbSet FourthDummyEntities { get; set; } + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/AbpEfCoreTestSecondContextModule.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/AbpEfCoreTestSecondContextModule.cs index 80ece93c07..e5e02efa3b 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/AbpEfCoreTestSecondContextModule.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/AbpEfCoreTestSecondContextModule.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext; using Volo.Abp.Modularity; using Volo.Abp.Threading; @@ -19,6 +20,11 @@ namespace Volo.Abp.EntityFrameworkCore.TestApp.SecondContext { options.AddDefaultRepositories(); }); + + context.Services.AddAbpDbContext(options => + { + options.AddDefaultRepositories(); + }); } public override void OnApplicationInitialization(ApplicationInitializationContext context) @@ -36,4 +42,4 @@ namespace Volo.Abp.EntityFrameworkCore.TestApp.SecondContext } } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs index a1ca2e2846..4f8faef65e 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs @@ -39,7 +39,7 @@ namespace Volo.Abp.EntityFrameworkCore { opt.DefaultWithDetailsFunc = q => q.Include(p => p.Phones); }); - + options.Entity(opt => { opt.DefaultWithDetailsFunc = q => q.Include(p => p.Books); @@ -76,7 +76,7 @@ namespace Volo.Abp.EntityFrameworkCore @"CREATE VIEW View_PersonView AS SELECT Name, CreationTime, Birthday, LastActive FROM People"); } - + return connection; } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs index 8fd88f23fe..4e343e7331 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Shouldly; using Volo.Abp.Domain.Repositories; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext; using Volo.Abp.TestApp.Domain; using Volo.Abp.TestApp.EntityFrameworkCore; @@ -15,13 +16,15 @@ namespace Volo.Abp.EntityFrameworkCore public class DbContext_Replace_Tests : EntityFrameworkCoreTestBase { private readonly IBasicRepository _dummyRepository; - private readonly IPersonRepository _personRepository; + private readonly IBasicRepository _fourthDummyRepository; + private readonly IPersonRepository _personRepository; private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly AbpDbContextOptions _options; public DbContext_Replace_Tests() { _dummyRepository = GetRequiredService>(); + _fourthDummyRepository = GetRequiredService>(); _personRepository = GetRequiredService(); _unitOfWorkManager = GetRequiredService(); _options = GetRequiredService>().Value; @@ -31,8 +34,10 @@ namespace Volo.Abp.EntityFrameworkCore public async Task Should_Replace_DbContext() { _options.GetReplacedTypeOrSelf(typeof(IThirdDbContext)).ShouldBe(typeof(TestAppDbContext)); - + _options.GetReplacedTypeOrSelf(typeof(IFourthDbContext)).ShouldBe(typeof(TestAppDbContext)); + (ServiceProvider.GetRequiredService() is TestAppDbContext).ShouldBeTrue(); + (ServiceProvider.GetRequiredService() is TestAppDbContext).ShouldBeTrue(); using (var uow = _unitOfWorkManager.Begin()) { @@ -44,11 +49,19 @@ namespace Volo.Abp.EntityFrameworkCore var instance3 = await _personRepository.GetDbContextAsync(); (instance3 is TestAppDbContext).ShouldBeTrue(); - + + var instance4 = await _fourthDummyRepository.GetDbContextAsync(); + (instance4 is IFourthDbContext).ShouldBeTrue(); + + var instance5 = await _fourthDummyRepository.GetDbContextAsync(); + (instance5 is TestAppDbContext).ShouldBeTrue(); + // All instances should be the same! instance3.ShouldBe(instance1); instance3.ShouldBe(instance2); - + instance3.ShouldBe(instance4); + instance3.ShouldBe(instance5); + await uow.CompleteAsync(); } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs index da8bbc8a6c..cd8bb75b78 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs @@ -1,12 +1,17 @@ using Microsoft.EntityFrameworkCore; +using Volo.Abp.DependencyInjection; using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext; using Volo.Abp.TestApp.Domain; namespace Volo.Abp.TestApp.EntityFrameworkCore { - public class TestAppDbContext : AbpDbContext, IThirdDbContext + [ReplaceDbContext(typeof(IFourthDbContext))] + public class TestAppDbContext : AbpDbContext, IThirdDbContext, IFourthDbContext { + private DbSet _dummyEntities; + private DbSet _dummyEntities1; public DbSet People { get; set; } public DbSet Cities { get; set; } @@ -16,10 +21,12 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore public DbSet DummyEntities { get; set; } public DbSet EntityWithIntPks { get; set; } - + public DbSet Author { get; set; } - public TestAppDbContext(DbContextOptions options) + public DbSet FourthDummyEntities { get; set; } + + public TestAppDbContext(DbContextOptions options) : base(options) { diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs index 2ac327e5e7..bd35016989 100644 --- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs @@ -46,7 +46,7 @@ namespace Volo.Abp.Http.DynamicProxying { var dateTime1 = new DateTime(2020, 04, 19, 19, 05, 01); var result = await _controller.GetWithDateTimeParameterAsync(dateTime1); - result.ShouldBe(dateTime1); + result.ToUniversalTime().ShouldBe(dateTime1.ToUniversalTime()); } [Fact] @@ -56,7 +56,7 @@ namespace Volo.Abp.Http.DynamicProxying { var dateTime1 = new DateTime(2020, 04, 19, 19, 05, 01); var result = await _controller.GetWithDateTimeParameterAsync(dateTime1); - result.ShouldBe(dateTime1); + result.ToUniversalTime().ShouldBe(dateTime1.ToUniversalTime()); } } diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/fi.json b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/fi.json new file mode 100644 index 0000000000..2549056076 --- /dev/null +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/fi.json @@ -0,0 +1,6 @@ +{ + "culture": "fi", + "texts": { + "Volo.Abp.Http.DynamicProxying:10001": "Yrityspoikkeus ja tiedot: {0}" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/fr.json b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/fr.json new file mode 100644 index 0000000000..6690705ba2 --- /dev/null +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/fr.json @@ -0,0 +1,6 @@ +{ + "culture": "fr", + "texts": { + "Volo.Abp.Http.DynamicProxying:10001": "Exception métier avec données: {0}" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/hi.json b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/hi.json new file mode 100644 index 0000000000..8e10f1518b --- /dev/null +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/hi.json @@ -0,0 +1,6 @@ +{ + "culture": "hi", + "texts": { + "Volo.Abp.Http.DynamicProxying:10001": "डेटा के साथ व्यावसायिक अपवाद: {0}" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/it.json b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/it.json new file mode 100644 index 0000000000..4920b4a0e4 --- /dev/null +++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Localization/it.json @@ -0,0 +1,6 @@ +{ + "culture": "it", + "texts": { + "Volo.Abp.Http.DynamicProxying:10001": "Eccezione aziendale con dati: {0}" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/FR.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/FR.json new file mode 100644 index 0000000000..f1cc5293ca --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/FR.json @@ -0,0 +1,7 @@ +{ + "culture": "fr", + "texts": { + "USA": "les états-unis d'Amérique", + "Brazil": "Brésil" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/fi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/fi.json new file mode 100644 index 0000000000..7a031f8c41 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/fi.json @@ -0,0 +1,7 @@ +{ + "culture": "fi", + "texts": { + "USA": "Yhdysvallat", + "Brazil": "Brasilia" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/hi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/hi.json new file mode 100644 index 0000000000..9917b1efd5 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/hi.json @@ -0,0 +1,7 @@ +{ + "culture": "hi", + "texts": { + "USA": "संयुक्त राज्य अमेरिका", + "Brazil": "ब्राज़िल" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/it.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/it.json new file mode 100644 index 0000000000..965756dd99 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/it.json @@ -0,0 +1,7 @@ +{ + "culture": "it", + "texts": { + "USA": "Stati Uniti d'America", + "Brazil": "Brasile" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/FR.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/FR.json new file mode 100644 index 0000000000..32fac7bf02 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/FR.json @@ -0,0 +1,7 @@ +{ + "culture": "fr", + "texts": { + "ThisFieldIsRequired": "Ce champ est requis", + "MaxLenghtErrorMessage": "Ce champ peut contenir au maximum \"{0}\" caractères" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/fi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/fi.json new file mode 100644 index 0000000000..b2d289d3c7 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/fi.json @@ -0,0 +1,7 @@ +{ + "culture": "fi", + "texts": { + "ThisFieldIsRequired": "Tämä kenttä pitää täyttää", + "MaxLenghtErrorMessage": "Tämä kenttä voi olla enintään {0} merkkiä" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/hi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/hi.json new file mode 100644 index 0000000000..a1e297d853 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/hi.json @@ -0,0 +1,7 @@ +{ + "culture": "hi", + "texts": { + "ThisFieldIsRequired": "यह फ़ील्ड आवश्यक है", + "MaxLenghtErrorMessage": "यह क्षेत्र अधिकतम '{0}' वर्ण का हो सकता है" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/it.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/it.json new file mode 100644 index 0000000000..1279ed4fe7 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/it.json @@ -0,0 +1,7 @@ +{ + "culture": "it", + "texts": { + "ThisFieldIsRequired": "Questo campo è obbligatorio", + "MaxLenghtErrorMessage": "Questo campo può contenere un massimo di caratteri \"{0}\"" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/FR.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/FR.json new file mode 100644 index 0000000000..ab5f63ad78 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/FR.json @@ -0,0 +1,11 @@ +{ + "culture": "fr", + "texts": { + "Hello {0}.": "Bonjour {0} .", + "Car": "Voiture", + "CarPlural": "Voitures", + "MaxLenghtErrorMessage": "La longueur de ce champ peut être au maximum de \"{0}\" caractères", + "Universe": "Univers", + "FortyTwo": "Quarante-deux" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/fi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/fi.json new file mode 100644 index 0000000000..74eabcd747 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/fi.json @@ -0,0 +1,11 @@ +{ + "culture": "fi", + "texts": { + "Hello {0}.": "Hei {0} .", + "Car": "Auto", + "CarPlural": "Autot", + "MaxLenghtErrorMessage": "Tämän kentän pituus voi olla enintään {0} merkkiä", + "Universe": "Maailmankaikkeus", + "FortyTwo": "Neljäkymmentäkaksi" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/hi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/hi.json new file mode 100644 index 0000000000..22573158a4 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/hi.json @@ -0,0 +1,11 @@ +{ + "culture": "hi", + "texts": { + "Hello {0}.": "नमस्ते {0} ।", + "Car": "गाड़ी", + "CarPlural": "कारों", + "MaxLenghtErrorMessage": "इस क्षेत्र की लंबाई अधिकतम '{0}' वर्ण हो सकती है", + "Universe": "ब्रम्हांड", + "FortyTwo": "बयालीस" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/it.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/it.json new file mode 100644 index 0000000000..677afdd19e --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/it.json @@ -0,0 +1,11 @@ +{ + "culture": "it", + "texts": { + "Hello {0}.": "Salve {0} .", + "Car": "Auto", + "CarPlural": "Automobili", + "MaxLenghtErrorMessage": "La lunghezza di questo campo può essere al massimo di caratteri \"{0}\"", + "Universe": "Universo", + "FortyTwo": "Quarantadue" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/FR.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/FR.json new file mode 100644 index 0000000000..e74ca8ed74 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/FR.json @@ -0,0 +1,6 @@ +{ + "culture": "fr", + "texts": { + "SeeYou": "À bientôt" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/fi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/fi.json new file mode 100644 index 0000000000..456c75dfa8 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/fi.json @@ -0,0 +1,6 @@ +{ + "culture": "fi", + "texts": { + "SeeYou": "Nähdään" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/hi.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/hi.json new file mode 100644 index 0000000000..b05c0205f4 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/hi.json @@ -0,0 +1,6 @@ +{ + "culture": "hi", + "texts": { + "SeeYou": "फिर मिलते हैं" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo.Abp.MongoDB.Tests.SecondContext.csproj b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo.Abp.MongoDB.Tests.SecondContext.csproj new file mode 100644 index 0000000000..e779329ad7 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo.Abp.MongoDB.Tests.SecondContext.csproj @@ -0,0 +1,19 @@ + + + + + + net5.0 + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + true + true + true + true + + + + + + + + diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContext.cs new file mode 100644 index 0000000000..7b496f954f --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContext.cs @@ -0,0 +1,13 @@ +using MongoDB.Driver; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; + +namespace Volo.Abp.MongoDB.TestApp.FourthContext +{ + /* This dbcontext is just for testing to replace dbcontext from the application using ReplaceDbContextAttribute + */ + public class FourthDbContext : AbpMongoDbContext, IFourthDbContext + { + public IMongoCollection FourthDummyEntities => Collection(); + + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContextDummyEntity.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContextDummyEntity.cs new file mode 100644 index 0000000000..8043301215 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContextDummyEntity.cs @@ -0,0 +1,10 @@ +using System; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.EntityFrameworkCore.TestApp.FourthContext +{ + public class FourthDbContextDummyEntity : AggregateRoot + { + public string Value { get; set; } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/IFourthDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/IFourthDbContext.cs new file mode 100644 index 0000000000..ae9ee2f281 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/IFourthDbContext.cs @@ -0,0 +1,10 @@ +using MongoDB.Driver; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; + +namespace Volo.Abp.MongoDB.TestApp.FourthContext +{ + public interface IFourthDbContext : IAbpMongoDbContext + { + IMongoCollection FourthDummyEntities { get;} + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/AbpMongoDbTestSecondContextModule.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/AbpMongoDbTestSecondContextModule.cs new file mode 100644 index 0000000000..ba5eaf7f79 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/AbpMongoDbTestSecondContextModule.cs @@ -0,0 +1,45 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; +using Volo.Abp.MongoDB.TestApp.FourthContext; +using Volo.Abp.MongoDB.TestApp.ThirdDbContext; +using Volo.Abp.Threading; + +namespace Volo.Abp.MongoDB.TestApp.SecondContext +{ + [DependsOn(typeof(AbpMongoDbModule))] + public class AbpMongoDbTestSecondContextModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddMongoDbContext(options => + { + options.AddDefaultRepositories(); + }); + + context.Services.AddMongoDbContext(options => + { + options.AddDefaultRepositories(); + }); + + context.Services.AddMongoDbContext(options => + { + options.AddDefaultRepositories(); + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + using (var scope = context.ServiceProvider.CreateScope()) + { + AsyncHelper.RunSync(() => scope.ServiceProvider + .GetRequiredService() + .BuildAsync()); + } + } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/BookInSecondDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/BookInSecondDbContext.cs new file mode 100644 index 0000000000..d7e81f4258 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/BookInSecondDbContext.cs @@ -0,0 +1,21 @@ +using System; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.MongoDB.TestApp.SecondContext +{ + public class BookInSecondDbContext : AggregateRoot + { + public string Name { get; set; } + + public BookInSecondDbContext() + { + + } + + public BookInSecondDbContext(Guid id, string name) + : base(id) + { + Name = name; + } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/PhoneInSecondDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/PhoneInSecondDbContext.cs new file mode 100644 index 0000000000..d808d5a52a --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/PhoneInSecondDbContext.cs @@ -0,0 +1,18 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.MongoDB.TestApp.SecondContext +{ + public class PhoneInSecondDbContext : AggregateRoot + { + public virtual Guid PersonId { get; set; } + + public virtual string Number { get; set; } + + public override object[] GetKeys() + { + return new object[] {PersonId, Number}; + } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondContextTestDataBuilder.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondContextTestDataBuilder.cs new file mode 100644 index 0000000000..c3fb902c64 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondContextTestDataBuilder.cs @@ -0,0 +1,30 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Guids; + +namespace Volo.Abp.MongoDB.TestApp.SecondContext +{ + public class SecondContextTestDataBuilder : ITransientDependency + { + private readonly IBasicRepository _bookRepository; + private readonly IGuidGenerator _guidGenerator; + + public SecondContextTestDataBuilder(IBasicRepository bookRepository, IGuidGenerator guidGenerator) + { + _bookRepository = bookRepository; + _guidGenerator = guidGenerator; + } + + public async Task BuildAsync() + { + await _bookRepository.InsertAsync( + new BookInSecondDbContext( + _guidGenerator.Create(), + "TestBook1" + ) + ); + } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondDbContext.cs new file mode 100644 index 0000000000..2df5785b20 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondDbContext.cs @@ -0,0 +1,11 @@ +using MongoDB.Driver; + +namespace Volo.Abp.MongoDB.TestApp.SecondContext +{ + public class SecondDbContext : AbpMongoDbContext + { + public IMongoCollection Books => Collection(); + + public IMongoCollection Phones => Collection(); + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/IThirdDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/IThirdDbContext.cs new file mode 100644 index 0000000000..cfe629b5a7 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/IThirdDbContext.cs @@ -0,0 +1,9 @@ +using MongoDB.Driver; + +namespace Volo.Abp.MongoDB.TestApp.ThirdDbContext +{ + public interface IThirdDbContext : IAbpMongoDbContext + { + IMongoCollection DummyEntities { get; } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContext.cs new file mode 100644 index 0000000000..c3b018a699 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContext.cs @@ -0,0 +1,11 @@ +using MongoDB.Driver; + +namespace Volo.Abp.MongoDB.TestApp.ThirdDbContext +{ + /* This dbcontext is just for testing to replace dbcontext from the application using AbpDbContextRegistrationOptions.ReplaceDbContext + */ + public class ThirdDbContext : AbpMongoDbContext, IThirdDbContext + { + public IMongoCollection DummyEntities => Collection(); + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContextDummyEntity.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContextDummyEntity.cs new file mode 100644 index 0000000000..a784406ff5 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContextDummyEntity.cs @@ -0,0 +1,10 @@ +using System; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.MongoDB.TestApp.ThirdDbContext +{ + public class ThirdDbContextDummyEntity : AggregateRoot + { + public string Value { get; set; } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj index c36fbb799c..21bcac616e 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj @@ -9,8 +9,8 @@ - + diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs index e580c6fce6..100011560e 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs @@ -1,21 +1,18 @@ using System; -using System.Linq; -using System.Threading; using Microsoft.Extensions.DependencyInjection; -using MongoDB.Driver; -using MongoDB.Driver.Core.Servers; using Volo.Abp.Data; using Volo.Abp.Modularity; +using Volo.Abp.MongoDB.TestApp.SecondContext; +using Volo.Abp.MongoDB.TestApp.ThirdDbContext; using Volo.Abp.TestApp; using Volo.Abp.TestApp.Domain; using Volo.Abp.TestApp.MongoDB; -using Volo.Abp.Uow; namespace Volo.Abp.MongoDB { [DependsOn( - typeof(AbpMongoDbModule), - typeof(TestAppModule) + typeof(TestAppModule), + typeof(AbpMongoDbTestSecondContextModule) )] public class AbpMongoDbTestModule : AbpModule { @@ -35,6 +32,8 @@ namespace Volo.Abp.MongoDB { options.AddDefaultRepositories(); options.AddRepository(); + + options.ReplaceDbContext(); }); } } diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DbContext_Replace_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DbContext_Replace_Tests.cs new file mode 100644 index 0000000000..eefa6852bf --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DbContext_Replace_Tests.cs @@ -0,0 +1,31 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Shouldly; +using Volo.Abp.MongoDB.TestApp.FourthContext; +using Volo.Abp.MongoDB.TestApp.ThirdDbContext; +using Volo.Abp.TestApp.MongoDB; +using Xunit; + +namespace Volo.Abp.MongoDB +{ + [Collection(MongoTestCollection.Name)] + public class DbContext_Replace_Tests : MongoDbTestBase + { + private readonly AbpMongoDbContextOptions _options; + + public DbContext_Replace_Tests() + { + _options = GetRequiredService>().Value; + } + + [Fact] + public void Should_Replace_DbContext() + { + _options.GetReplacedTypeOrSelf(typeof(IThirdDbContext)).ShouldBe(typeof(TestAppMongoDbContext)); + _options.GetReplacedTypeOrSelf(typeof(IFourthDbContext)).ShouldBe(typeof(TestAppMongoDbContext)); + + (ServiceProvider.GetRequiredService() is TestAppMongoDbContext).ShouldBeTrue(); + (ServiceProvider.GetRequiredService() is TestAppMongoDbContext).ShouldBeTrue(); + } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs index eed8d4ade3..68a2856e01 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs @@ -1,12 +1,17 @@ using MongoDB.Driver; using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; using Volo.Abp.MongoDB; +using Volo.Abp.MongoDB.TestApp.FourthContext; +using Volo.Abp.MongoDB.TestApp.ThirdDbContext; using Volo.Abp.TestApp.Domain; namespace Volo.Abp.TestApp.MongoDB { [ConnectionStringName("TestApp")] - public class TestAppMongoDbContext : AbpMongoDbContext, ITestAppMongoDbContext + [ReplaceDbContext(typeof(IFourthDbContext))] + public class TestAppMongoDbContext : AbpMongoDbContext, ITestAppMongoDbContext, IThirdDbContext, IFourthDbContext { [MongoCollection("Persons")] //Intentionally changed the collection name to test it public IMongoCollection People => Collection(); @@ -15,6 +20,10 @@ namespace Volo.Abp.TestApp.MongoDB public IMongoCollection Cities => Collection(); + public IMongoCollection DummyEntities => Collection(); + + public IMongoCollection FourthDummyEntities => Collection(); + protected internal override void CreateModel(IMongoModelBuilder modelBuilder) { base.CreateModel(modelBuilder); diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo.Abp.TextTemplating.Razor.Tests.csproj b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo.Abp.TextTemplating.Razor.Tests.csproj new file mode 100644 index 0000000000..7161e0520a --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo.Abp.TextTemplating.Razor.Tests.csproj @@ -0,0 +1,22 @@ + + + + + + net5.0 + + + + + + Always + + + + + + + + + + diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions_Tests.cs new file mode 100644 index 0000000000..9f4cd3ecaa --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/AbpCompiledViewProviderOptions_Tests.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.TextTemplating.Razor.SampleTemplates; +using Xunit; + +namespace Volo.Abp.TextTemplating.Razor +{ + public class AbpCompiledViewProviderOptions_Tests : TemplateDefinitionTests + { + private readonly IAbpCompiledViewProvider _compiledViewProvider; + private readonly ITemplateDefinitionManager _templateDefinitionManager; + + public AbpCompiledViewProviderOptions_Tests() + { + _templateDefinitionManager = GetRequiredService(); + _compiledViewProvider = GetRequiredService(); + } + + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure(options => + { + options.TemplateReferences.Add(RazorTestTemplates.TestTemplate, new List() + { + Assembly.Load("Microsoft.Extensions.Logging.Abstractions") + } + .Select(x => MetadataReference.CreateFromFile(x.Location)) + .ToList()); + }); + base.AfterAddApplication(services); + } + + [Fact] + public async Task Custom_TemplateReferences_Test() + { + var templateDefinition = _templateDefinitionManager.GetOrNull(RazorTestTemplates.TestTemplate); + + var assembly = await _compiledViewProvider.GetAssemblyAsync(templateDefinition); + + assembly.GetReferencedAssemblies().ShouldContain(x => x.Name == "Microsoft.Extensions.Logging.Abstractions"); + } + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorLocalizedTemplateContentReaderFactory_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorLocalizedTemplateContentReaderFactory_Tests.cs new file mode 100644 index 0000000000..28ecb6db52 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorLocalizedTemplateContentReaderFactory_Tests.cs @@ -0,0 +1,26 @@ +using System; +using System.IO; +using Microsoft.Extensions.FileProviders; +using Volo.Abp.TextTemplating.VirtualFiles; + +namespace Volo.Abp.TextTemplating.Razor +{ + public class RazorLocalizedTemplateContentReaderFactory_Tests : LocalizedTemplateContentReaderFactory_Tests + { + public RazorLocalizedTemplateContentReaderFactory_Tests() + { + LocalizedTemplateContentReaderFactory = new LocalizedTemplateContentReaderFactory( + new PhysicalFileVirtualFileProvider( + new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), + "Volo", "Abp", "TextTemplating", "Razor")))); + + WelcomeEmailEnglishContent = "@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase" + + Environment.NewLine + + "Welcome @Model.Name to the abp.io!"; + + WelcomeEmailTurkishContent = "@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase" + + Environment.NewLine + + "Merhaba @Model.Name, abp.io'ya hoşgeldiniz!"; + } + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateDefinitionTests.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateDefinitionTests.cs new file mode 100644 index 0000000000..53c40b5ea8 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateDefinitionTests.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.TextTemplating.Razor +{ + public class RazorTemplateDefinitionTests : TemplateDefinitionTests + { + + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateRendererProvider_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateRendererProvider_Tests.cs new file mode 100644 index 0000000000..04e2d1b029 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTemplateRendererProvider_Tests.cs @@ -0,0 +1,145 @@ +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.TextTemplating.Razor +{ + public class RazorTemplateRendererProvider_Tests : AbpTextTemplatingTestBase + { + private readonly ITemplateRenderer _templateRenderer; + + public RazorTemplateRendererProvider_Tests() + { + _templateRenderer = GetRequiredService(); + } + + [Fact] + public async Task Should_Get_Rendered_Localized_Template_Content_With_Different_Cultures() + { + (await _templateRenderer.RenderAsync( + TestTemplates.WelcomeEmail, + model: new WelcomeEmailModel() + { + Name = "John" + }, + cultureName: "en" + )).ShouldBe("Welcome John to the abp.io!"); + + (await _templateRenderer.RenderAsync( + TestTemplates.WelcomeEmail, + model: new WelcomeEmailModel() + { + Name = "John" + }, + cultureName: "tr" + )).ShouldBe("Merhaba John, abp.io'ya hoşgeldiniz!"); + + //"en-US" fallbacks to "en" since "en-US" doesn't exists and "en" is the fallback culture + (await _templateRenderer.RenderAsync( + TestTemplates.WelcomeEmail, + model: new WelcomeEmailModel() + { + Name = "John" + }, + cultureName: "en-US" + )).ShouldBe("Welcome John to the abp.io!"); + + //"fr" fallbacks to "en" since "fr" doesn't exists and "en" is the default culture + (await _templateRenderer.RenderAsync( + TestTemplates.WelcomeEmail, + model: new WelcomeEmailModel() + { + Name = "John" + }, + cultureName: "fr" + )).ShouldBe("Welcome John to the abp.io!"); + } + + [Fact] + public async Task Should_Get_Rendered_Localized_Template_Content_With_Stronly_Typed_Model() + { + (await _templateRenderer.RenderAsync( + TestTemplates.WelcomeEmail, + model: new WelcomeEmailModel("John"), + cultureName: "en" + )).ShouldBe("Welcome John to the abp.io!"); + } + + [Fact] + public async Task Should_Get_Rendered_Inline_Localized_Template() + { + (await _templateRenderer.RenderAsync( + TestTemplates.ForgotPasswordEmail, + new ForgotPasswordEmailModel("John"), + cultureName: "en" + )).ShouldBe("*BEGIN*Hello John, how are you?. Please click to the following link to get an email to reset your password!*END*"); + + (await _templateRenderer.RenderAsync( + TestTemplates.ForgotPasswordEmail, + new ForgotPasswordEmailModel("John"), + cultureName: "tr" + )).ShouldBe("*BEGIN*Merhaba John, nasılsın?. Please click to the following link to get an email to reset your password!*END*"); + } + + [Fact] + public async Task Should_Get_Localized_Numbers() + { + (await _templateRenderer.RenderAsync( + TestTemplates.ShowDecimalNumber, + new ShowDecimalNumberModel(123.45M), + cultureName: "en" + )).ShouldBe("*BEGIN*123.45*END*"); + + (await _templateRenderer.RenderAsync( + TestTemplates.ShowDecimalNumber, + new ShowDecimalNumberModel(123.45M), + cultureName: "de" + )).ShouldBe("*BEGIN*123,45*END*"); + } + + public class WelcomeEmailModel + { + public string Name { get; set; } + + public WelcomeEmailModel() + { + + } + + public WelcomeEmailModel(string name) + { + Name = name; + } + } + + public class ForgotPasswordEmailModel + { + public string Name { get; set; } + + public ForgotPasswordEmailModel() + { + + } + + public ForgotPasswordEmailModel(string name) + { + Name = name; + } + } + + public class ShowDecimalNumberModel + { + public decimal Amount { get; set; } + + public ShowDecimalNumberModel() + { + + } + + public ShowDecimalNumberModel(decimal amount) + { + Amount = amount; + } + } + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTestTemplateDefinitionProvider.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTestTemplateDefinitionProvider.cs new file mode 100644 index 0000000000..80f3f5f020 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTestTemplateDefinitionProvider.cs @@ -0,0 +1,28 @@ +using Volo.Abp.TextTemplating.Razor.SampleTemplates; + +namespace Volo.Abp.TextTemplating.Razor +{ + public class RazorTestTemplateDefinitionProvider : TemplateDefinitionProvider + { + public override void Define(ITemplateDefinitionContext context) + { + context.GetOrNull(TestTemplates.WelcomeEmail)? + .WithVirtualFilePath("/SampleTemplates/WelcomeEmail", false) + .WithRazorEngine(); + + context.GetOrNull(TestTemplates.ForgotPasswordEmail)? + .WithVirtualFilePath("/SampleTemplates/ForgotPasswordEmail.cshtml", true) + .WithRazorEngine(); + + context.GetOrNull(TestTemplates.TestTemplateLayout1)? + .WithVirtualFilePath("/SampleTemplates/TestTemplateLayout1.cshtml", true) + .WithRazorEngine(); + + context.GetOrNull(TestTemplates.ShowDecimalNumber)? + .WithVirtualFilePath("/SampleTemplates/ShowDecimalNumber.cshtml", true) + .WithRazorEngine(); + + context.Add(new TemplateDefinition(RazorTestTemplates.TestTemplate).WithVirtualFilePath("/SampleTemplates/TestTemplate.cshtml", true)); + } + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTextTemplatingTestModule.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTextTemplatingTestModule.cs new file mode 100644 index 0000000000..74d7add887 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorTextTemplatingTestModule.cs @@ -0,0 +1,25 @@ +using Microsoft.CodeAnalysis; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; + +namespace Volo.Abp.TextTemplating.Razor +{ + [DependsOn( + typeof(AbpTextTemplatingTestModule) + )] + public class RazorTextTemplatingTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded("Volo.Abp.TextTemplating.Razor"); + }); + + Configure(options => + { + options.References.Add(MetadataReference.CreateFromFile(typeof(RazorTextTemplatingTestModule).Assembly.Location)); + }); + } + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorVirtualFileTemplateContributor_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorVirtualFileTemplateContributor_Tests.cs new file mode 100644 index 0000000000..5bbb267613 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/RazorVirtualFileTemplateContributor_Tests.cs @@ -0,0 +1,23 @@ +using System; +using Volo.Abp.TextTemplating.VirtualFiles; + +namespace Volo.Abp.TextTemplating.Razor +{ + public class RazorVirtualFileTemplateContributor_Tests : VirtualFileTemplateContributor_Tests + { + public RazorVirtualFileTemplateContributor_Tests() + { + WelcomeEmailEnglishContent = "@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase" + + Environment.NewLine + + "Welcome @Model.Name to the abp.io!"; + + WelcomeEmailTurkishContent = "@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase" + + Environment.NewLine + + "Merhaba @Model.Name, abp.io'ya hoşgeldiniz!"; + + ForgotPasswordEmailEnglishContent = "@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase" + + Environment.NewLine + + "@Localizer[\"HelloText\", Model.Name], @Localizer[\"HowAreYou\"]. Please click to the following link to get an email to reset your password!"; + } + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ForgotPasswordEmail.cshtml b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ForgotPasswordEmail.cshtml new file mode 100644 index 0000000000..360e5b2a7c --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ForgotPasswordEmail.cshtml @@ -0,0 +1,2 @@ +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase +@Localizer["HelloText", Model.Name], @Localizer["HowAreYou"]. Please click to the following link to get an email to reset your password! \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/RazorTestTemplates.cs b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/RazorTestTemplates.cs new file mode 100644 index 0000000000..3fa87f7d90 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/RazorTestTemplates.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.TextTemplating.Razor.SampleTemplates +{ + public static class RazorTestTemplates + { + public const string TestTemplate = "TestTemplate"; + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ShowDecimalNumber.cshtml b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ShowDecimalNumber.cshtml new file mode 100644 index 0000000000..64a133f903 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/ShowDecimalNumber.cshtml @@ -0,0 +1,2 @@ +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase +@Model.Amount \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/TestTemplate.cshtml b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/TestTemplate.cshtml new file mode 100644 index 0000000000..3de93e1e40 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/TestTemplate.cshtml @@ -0,0 +1,6 @@ +@using Microsoft.Extensions.DependencyInjection +@using Microsoft.Extensions.Logging +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase +@{ + var loggerFactory = ServiceProvider.GetService(); +} diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/TestTemplateLayout1.cshtml b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/TestTemplateLayout1.cshtml new file mode 100644 index 0000000000..4d3bc7b7c2 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/TestTemplateLayout1.cshtml @@ -0,0 +1,2 @@ +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase +*BEGIN*@Body*END* \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/en.cshtml b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/en.cshtml new file mode 100644 index 0000000000..af025d39c3 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/en.cshtml @@ -0,0 +1,2 @@ +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase +Welcome @Model.Name to the abp.io! \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/tr.cshtml b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/tr.cshtml new file mode 100644 index 0000000000..c17e07bee1 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Razor.Tests/Volo/Abp/TextTemplating/Razor/SampleTemplates/WelcomeEmail/tr.cshtml @@ -0,0 +1,2 @@ +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase +Merhaba @Model.Name, abp.io'ya hoşgeldiniz! \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo.Abp.TextTemplating.Scriban.Tests.csproj b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo.Abp.TextTemplating.Scriban.Tests.csproj new file mode 100644 index 0000000000..1cdcf89ab9 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo.Abp.TextTemplating.Scriban.Tests.csproj @@ -0,0 +1,22 @@ + + + + + + net5.0 + + + + + + Always + + + + + + + + + + diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ForgotPasswordEmail.tpl b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ForgotPasswordEmail.tpl similarity index 100% rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ForgotPasswordEmail.tpl rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ForgotPasswordEmail.tpl diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ShowDecimalNumber.tpl b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ShowDecimalNumber.tpl similarity index 100% rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/ShowDecimalNumber.tpl rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/ShowDecimalNumber.tpl diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestTemplateLayout1.tpl b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/TestTemplateLayout1.tpl similarity index 100% rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestTemplateLayout1.tpl rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/TestTemplateLayout1.tpl diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/en.tpl b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/WelcomeEmail/en.tpl similarity index 100% rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/en.tpl rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/WelcomeEmail/en.tpl diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/tr.tpl b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/WelcomeEmail/tr.tpl similarity index 100% rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/WelcomeEmail/tr.tpl rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/SampleTemplates/WelcomeEmail/tr.tpl diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanLocalizedTemplateContentReaderFactory_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanLocalizedTemplateContentReaderFactory_Tests.cs new file mode 100644 index 0000000000..1757bdaa17 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanLocalizedTemplateContentReaderFactory_Tests.cs @@ -0,0 +1,20 @@ +using System.IO; +using Microsoft.Extensions.FileProviders; +using Volo.Abp.TextTemplating.VirtualFiles; + +namespace Volo.Abp.TextTemplating.Scriban +{ + public class ScribanLocalizedTemplateContentReaderFactory_Tests : LocalizedTemplateContentReaderFactory_Tests + { + public ScribanLocalizedTemplateContentReaderFactory_Tests() + { + LocalizedTemplateContentReaderFactory = new LocalizedTemplateContentReaderFactory( + new PhysicalFileVirtualFileProvider( + new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), + "Volo", "Abp", "TextTemplating", "Scriban")))); + + WelcomeEmailEnglishContent = "Welcome {{model.name}} to the abp.io!"; + WelcomeEmailTurkishContent = "Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!"; + } + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateDefinitionTests.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateDefinitionTests.cs new file mode 100644 index 0000000000..e454af36ef --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateDefinitionTests.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.TextTemplating.Scriban +{ + public class ScribanTemplateDefinitionTests : TemplateDefinitionTests + { + + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRendererProvider_Tests.cs similarity index 95% rename from framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs rename to framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRendererProvider_Tests.cs index ca4ae3e3fd..cc0e45828b 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateRenderer_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTemplateRendererProvider_Tests.cs @@ -3,13 +3,13 @@ using System.Threading.Tasks; using Shouldly; using Xunit; -namespace Volo.Abp.TextTemplating +namespace Volo.Abp.TextTemplating.Scriban { - public class TemplateRenderer_Tests : AbpTextTemplatingTestBase + public class ScribanTemplateRendererProvider_Tests : AbpTextTemplatingTestBase { private readonly ITemplateRenderer _templateRenderer; - public TemplateRenderer_Tests() + public ScribanTemplateRendererProvider_Tests() { _templateRenderer = GetRequiredService(); } @@ -91,7 +91,7 @@ namespace Volo.Abp.TextTemplating cultureName: "tr" )).ShouldBe("*BEGIN*Merhaba John, nasılsın?. Please click to the following link to get an email to reset your password!*END*"); } - + [Fact] public async Task Should_Get_Localized_Numbers() { diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTestTemplateDefinitionProvider.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTestTemplateDefinitionProvider.cs new file mode 100644 index 0000000000..c809bf49d6 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTestTemplateDefinitionProvider.cs @@ -0,0 +1,24 @@ +namespace Volo.Abp.TextTemplating.Scriban +{ + public class ScribanTestTemplateDefinitionProvider : TemplateDefinitionProvider + { + public override void Define(ITemplateDefinitionContext context) + { + context.GetOrNull(TestTemplates.WelcomeEmail)? + .WithVirtualFilePath("/SampleTemplates/WelcomeEmail", false) + .WithScribanEngine(); + + context.GetOrNull(TestTemplates.ForgotPasswordEmail)? + .WithVirtualFilePath("/SampleTemplates/ForgotPasswordEmail.tpl", true) + .WithScribanEngine(); + + context.GetOrNull(TestTemplates.TestTemplateLayout1)? + .WithVirtualFilePath("/SampleTemplates/TestTemplateLayout1.tpl", true) + .WithScribanEngine(); + + context.GetOrNull(TestTemplates.ShowDecimalNumber)? + .WithVirtualFilePath("/SampleTemplates/ShowDecimalNumber.tpl", true) + .WithScribanEngine(); + } + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTextTemplatingTestModule.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTextTemplatingTestModule.cs new file mode 100644 index 0000000000..ff9da00c36 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanTextTemplatingTestModule.cs @@ -0,0 +1,19 @@ +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; + +namespace Volo.Abp.TextTemplating.Scriban +{ + [DependsOn( + typeof(AbpTextTemplatingTestModule) + )] + public class ScribanTextTemplatingTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded("Volo.Abp.TextTemplating.Scriban"); + }); + } + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanVirtualFileTemplateContributor_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanVirtualFileTemplateContributor_Tests.cs new file mode 100644 index 0000000000..026b8abe59 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Scriban.Tests/Volo/Abp/TextTemplating/Scriban/ScribanVirtualFileTemplateContributor_Tests.cs @@ -0,0 +1,14 @@ +using Volo.Abp.TextTemplating.VirtualFiles; + +namespace Volo.Abp.TextTemplating.Scriban +{ + public class ScribanVirtualFileTemplateContributor_Tests : VirtualFileTemplateContributor_Tests + { + public ScribanVirtualFileTemplateContributor_Tests() + { + WelcomeEmailEnglishContent = "Welcome {{model.name}} to the abp.io!"; + WelcomeEmailTurkishContent = "Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!"; + ForgotPasswordEmailEnglishContent = "{{L \"HelloText\" model.name}}, {{L \"HowAreYou\" }}. Please click to the following link to get an email to reset your password!"; + } + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo.Abp.TextTemplating.Tests.csproj b/framework/test/Volo.Abp.TextTemplating.Tests/Volo.Abp.TextTemplating.Tests.csproj index 555c2934b0..b4964ed8e3 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo.Abp.TextTemplating.Tests.csproj +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo.Abp.TextTemplating.Tests.csproj @@ -10,15 +10,22 @@ + + Always + + Always + + + diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingOptions_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingOptions_Tests.cs index 294596c693..591f6c9caf 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingOptions_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingOptions_Tests.cs @@ -4,7 +4,7 @@ using Xunit; namespace Volo.Abp.TextTemplating { - public class AbpTextTemplatingOptions_Tests : AbpTextTemplatingTestBase + public class AbpTextTemplatingOptions_Tests : AbpTextTemplatingTestBase { private readonly AbpTextTemplatingOptions _options; @@ -21,4 +21,4 @@ namespace Volo.Abp.TextTemplating .ShouldContain(typeof(TestTemplateDefinitionProvider)); } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestBase.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestBase.cs index ca5dc20445..24f8bad395 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestBase.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestBase.cs @@ -1,8 +1,10 @@ -using Volo.Abp.Testing; +using Volo.Abp.Modularity; +using Volo.Abp.Testing; namespace Volo.Abp.TextTemplating { - public abstract class AbpTextTemplatingTestBase : AbpIntegratedTest + public abstract class AbpTextTemplatingTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule { protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) { diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestModule.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestModule.cs index 8e8b69e116..66577cea75 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestModule.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/AbpTextTemplatingTestModule.cs @@ -1,13 +1,18 @@ -using Volo.Abp.Autofac; +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Volo.Abp.Autofac; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.TextTemplating.Localization; +using Volo.Abp.TextTemplating.Razor; +using Volo.Abp.TextTemplating.Scriban; using Volo.Abp.VirtualFileSystem; namespace Volo.Abp.TextTemplating { [DependsOn( - typeof(AbpTextTemplatingModule), + typeof(AbpTextTemplatingScribanModule), + typeof(AbpTextTemplatingRazorModule), typeof(AbpTestBaseModule), typeof(AbpAutofacModule), typeof(AbpLocalizationModule) @@ -27,6 +32,15 @@ namespace Volo.Abp.TextTemplating .Add("en") .AddVirtualJson("/Localization"); }); + + Configure(options => + { + options.TemplateReferences.Add(TestTemplates.HybridTemplateRazor, + new List() + { + MetadataReference.CreateFromFile(typeof(AbpTextTemplatingTestModule).Assembly.Location) + }); + }); } } } diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/HybridTemplateRendererProvider_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/HybridTemplateRendererProvider_Tests.cs new file mode 100644 index 0000000000..f6fffc89a7 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/HybridTemplateRendererProvider_Tests.cs @@ -0,0 +1,46 @@ +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.TextTemplating +{ + public class HybridTemplateRendererProvider_Tests : AbpTextTemplatingTestBase + { + private readonly ITemplateRenderer _templateRenderer; + + public HybridTemplateRendererProvider_Tests() + { + _templateRenderer = GetRequiredService(); + } + + [Fact] + public async Task Should_Render_By_Scriban() + { + (await _templateRenderer.RenderAsync( + TestTemplates.HybridTemplateScriban, + model: new + { + name = "John" + } + )).ShouldBe("Hello John, how are you?"); + } + + [Fact] + public async Task Should_Render_By_Razor() + { + (await _templateRenderer.RenderAsync( + TestTemplates.HybridTemplateRazor, + model: new HybridModel + { + Name = "John" + } + )).ShouldBe("Hello John, how are you?"); + } + + public class HybridModel + { + public string Name { get; set; } + } + + } +} diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/fi.json b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/fi.json new file mode 100644 index 0000000000..a1938e1f84 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/fi.json @@ -0,0 +1,7 @@ +{ + "culture": "fi", + "texts": { + "HelloText": "Hei {0}", + "HowAreYou": "mitä kuuluu?" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/hi.json b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/hi.json new file mode 100644 index 0000000000..1f5eb39e16 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/hi.json @@ -0,0 +1,7 @@ +{ + "culture": "hi", + "texts": { + "HelloText": "नमस्ते {0}", + "HowAreYou": "क्या हाल है?" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/it.json b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/it.json new file mode 100644 index 0000000000..1081d7b301 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/Localization/it.json @@ -0,0 +1,7 @@ +{ + "culture": "it", + "texts": { + "HelloText": "Salve {0}", + "HowAreYou": "come va?" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestRazorTemplate.cshtml b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestRazorTemplate.cshtml new file mode 100644 index 0000000000..02cf7a82a8 --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestRazorTemplate.cshtml @@ -0,0 +1,2 @@ +@inherits Volo.Abp.TextTemplating.Razor.RazorTemplatePageBase +Hello @Model.Name, @Localizer["HowAreYou"] \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestScribanTemplate.tpl b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestScribanTemplate.tpl new file mode 100644 index 0000000000..d1b39f873c --- /dev/null +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/SampleTemplates/TestScribanTemplate.tpl @@ -0,0 +1 @@ +Hello {{model.name}}, {{L "HowAreYou" }} \ No newline at end of file diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs index 51c78cc13e..6fd97cd2d4 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TemplateDefinitionTests.cs @@ -1,25 +1,27 @@ using Shouldly; +using Volo.Abp.Modularity; using Xunit; namespace Volo.Abp.TextTemplating { - public class TemplateDefinitionTests : AbpTextTemplatingTestBase + public abstract class TemplateDefinitionTests : AbpTextTemplatingTestBase + where TStartupModule : IAbpModule { - private readonly ITemplateDefinitionManager _templateDefinitionManager; + protected readonly ITemplateDefinitionManager TemplateDefinitionManager; - public TemplateDefinitionTests() + protected TemplateDefinitionTests() { - _templateDefinitionManager = GetRequiredService(); + TemplateDefinitionManager = GetRequiredService(); } [Fact] public void Should_Retrieve_Template_Definition_By_Name() { - var welcomeEmailTemplate = _templateDefinitionManager.Get(TestTemplates.WelcomeEmail); + var welcomeEmailTemplate = TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail); welcomeEmailTemplate.Name.ShouldBe(TestTemplates.WelcomeEmail); welcomeEmailTemplate.IsInlineLocalized.ShouldBeFalse(); - var forgotPasswordEmailTemplate = _templateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail); + var forgotPasswordEmailTemplate = TemplateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail); forgotPasswordEmailTemplate.Name.ShouldBe(TestTemplates.ForgotPasswordEmail); forgotPasswordEmailTemplate.IsInlineLocalized.ShouldBeTrue(); } @@ -27,15 +29,15 @@ namespace Volo.Abp.TextTemplating [Fact] public void Should_Get_Null_If_Template_Not_Found() { - var definition = _templateDefinitionManager.GetOrNull("undefined-template"); + var definition = TemplateDefinitionManager.GetOrNull("undefined-template"); definition.ShouldBeNull(); } [Fact] public void Should_Retrieve_All_Template_Definitions() { - var definitions = _templateDefinitionManager.GetAll(); + var definitions = TemplateDefinitionManager.GetAll(); definitions.Count.ShouldBeGreaterThan(1); } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs index 9db711d70c..ee05ce5166 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplateDefinitionProvider.cs @@ -1,4 +1,6 @@ using Volo.Abp.TextTemplating.Localization; +using Volo.Abp.TextTemplating.Razor; +using Volo.Abp.TextTemplating.Scriban; namespace Volo.Abp.TextTemplating { @@ -10,7 +12,7 @@ namespace Volo.Abp.TextTemplating new TemplateDefinition( TestTemplates.WelcomeEmail, defaultCultureName: "en" - ).WithVirtualFilePath("/SampleTemplates/WelcomeEmail", false) + ) ); context.Add( @@ -18,22 +20,42 @@ namespace Volo.Abp.TextTemplating TestTemplates.ForgotPasswordEmail, localizationResource: typeof(TestLocalizationSource), layout: TestTemplates.TestTemplateLayout1 - ).WithVirtualFilePath("/SampleTemplates/ForgotPasswordEmail.tpl", true) + ) ); context.Add( new TemplateDefinition( TestTemplates.TestTemplateLayout1, isLayout: true - ).WithVirtualFilePath("/SampleTemplates/TestTemplateLayout1.tpl", true) + ) ); - + context.Add( new TemplateDefinition( TestTemplates.ShowDecimalNumber, localizationResource: typeof(TestLocalizationSource), layout: TestTemplates.TestTemplateLayout1 - ).WithVirtualFilePath("/SampleTemplates/ShowDecimalNumber.tpl", true) + ) + ); + + context.Add( + new TemplateDefinition( + TestTemplates.HybridTemplateScriban, + localizationResource: typeof(TestLocalizationSource), + layout: null + ) + .WithVirtualFilePath("/SampleTemplates/TestScribanTemplate.tpl", true) + .WithScribanEngine() + ); + + context.Add( + new TemplateDefinition( + TestTemplates.HybridTemplateRazor, + localizationResource: typeof(TestLocalizationSource), + layout: null + ) + .WithVirtualFilePath("/SampleTemplates/TestRazorTemplate.cshtml", true) + .WithRazorEngine() ); } } diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplates.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplates.cs index 29a8604f3b..25d8223b78 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplates.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/TestTemplates.cs @@ -6,5 +6,8 @@ public const string ForgotPasswordEmail = "ForgotPasswordEmail"; public const string TestTemplateLayout1 = "TestTemplateLayout1"; public const string ShowDecimalNumber = "ShowDecimalNumber"; + + public const string HybridTemplateRazor = "HybridTemplateRazor"; + public const string HybridTemplateScriban = "HybridTemplateScriban"; } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs index 63e526ac1d..7a56997031 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/LocalizedTemplateContentReaderFactory_Tests.cs @@ -1,37 +1,36 @@ -using System.IO; -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Primitives; using Shouldly; +using Volo.Abp.Modularity; using Volo.Abp.VirtualFileSystem; using Xunit; namespace Volo.Abp.TextTemplating.VirtualFiles { - public class LocalizedTemplateContentReaderFactory_Tests: AbpTextTemplatingTestBase + public abstract class LocalizedTemplateContentReaderFactory_Tests : AbpTextTemplatingTestBase + where TStartupModule : IAbpModule { - private readonly ITemplateDefinitionManager _templateDefinitionManager; + protected readonly ITemplateDefinitionManager TemplateDefinitionManager; + protected LocalizedTemplateContentReaderFactory LocalizedTemplateContentReaderFactory; + protected string WelcomeEmailEnglishContent; + protected string WelcomeEmailTurkishContent; - public LocalizedTemplateContentReaderFactory_Tests() + protected LocalizedTemplateContentReaderFactory_Tests() { - _templateDefinitionManager = GetRequiredService(); + TemplateDefinitionManager = GetRequiredService(); } [Fact] public async Task Create_Should_Work_With_PhysicalFileProvider() { - var localizedTemplateContentReaderFactory = new LocalizedTemplateContentReaderFactory( - new PhysicalFileVirtualFileProvider( - new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), - "Volo", "Abp", "TextTemplating")))); + var reader = await LocalizedTemplateContentReaderFactory.CreateAsync(TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail)); - var reader = await localizedTemplateContentReaderFactory.CreateAsync(_templateDefinitionManager.Get(TestTemplates.WelcomeEmail)); - - reader.GetContentOrNull("en").ShouldBe("Welcome {{model.name}} to the abp.io!"); - reader.GetContentOrNull("tr").ShouldBe("Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!"); + reader.GetContentOrNull("en").ShouldBe(WelcomeEmailEnglishContent); + reader.GetContentOrNull("tr").ShouldBe(WelcomeEmailTurkishContent); } - class PhysicalFileVirtualFileProvider : IVirtualFileProvider + public class PhysicalFileVirtualFileProvider : IVirtualFileProvider { private readonly PhysicalFileProvider _physicalFileProvider; diff --git a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs index e5c7138118..4862e61203 100644 --- a/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs +++ b/framework/test/Volo.Abp.TextTemplating.Tests/Volo/Abp/TextTemplating/VirtualFiles/VirtualFileTemplateContributor_Tests.cs @@ -1,45 +1,50 @@ using System.Threading.Tasks; using Shouldly; +using Volo.Abp.Modularity; using Xunit; namespace Volo.Abp.TextTemplating.VirtualFiles { - public class VirtualFileTemplateContributor_Tests : AbpTextTemplatingTestBase + public abstract class VirtualFileTemplateContributor_Tests : AbpTextTemplatingTestBase + where TStartupModule : IAbpModule { - private readonly ITemplateDefinitionManager _templateDefinitionManager; - private readonly VirtualFileTemplateContentContributor _virtualFileTemplateContentContributor; + protected readonly ITemplateDefinitionManager TemplateDefinitionManager; + protected readonly VirtualFileTemplateContentContributor VirtualFileTemplateContentContributor; + protected string WelcomeEmailEnglishContent; + protected string WelcomeEmailTurkishContent; + protected string ForgotPasswordEmailEnglishContent; - public VirtualFileTemplateContributor_Tests() + protected VirtualFileTemplateContributor_Tests() { - _templateDefinitionManager = GetRequiredService(); - _virtualFileTemplateContentContributor = GetRequiredService(); + TemplateDefinitionManager = GetRequiredService(); + VirtualFileTemplateContentContributor = GetRequiredService(); } [Fact] public async Task Should_Get_Localized_Content_By_Culture() { - (await _virtualFileTemplateContentContributor.GetOrNullAsync( - new TemplateContentContributorContext(_templateDefinitionManager.Get(TestTemplates.WelcomeEmail), + (await VirtualFileTemplateContentContributor.GetOrNullAsync( + new TemplateContentContributorContext(TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail), ServiceProvider, "en"))) - .ShouldBe("Welcome {{model.name}} to the abp.io!"); + .ShouldBe(WelcomeEmailEnglishContent); - (await _virtualFileTemplateContentContributor.GetOrNullAsync( - new TemplateContentContributorContext(_templateDefinitionManager.Get(TestTemplates.WelcomeEmail), + (await VirtualFileTemplateContentContributor.GetOrNullAsync( + new TemplateContentContributorContext(TemplateDefinitionManager.Get(TestTemplates.WelcomeEmail), ServiceProvider, "tr"))) - .ShouldBe("Merhaba {{model.name}}, abp.io'ya hoşgeldiniz!"); + .ShouldBe(WelcomeEmailTurkishContent); } [Fact] public async Task Should_Get_Non_Localized_Template_Content() { - (await _virtualFileTemplateContentContributor.GetOrNullAsync( + (await VirtualFileTemplateContentContributor.GetOrNullAsync( new TemplateContentContributorContext( - _templateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail), + TemplateDefinitionManager.Get(TestTemplates.ForgotPasswordEmail), ServiceProvider, null))) - .ShouldBe("{{L \"HelloText\" model.name}}, {{L \"HowAreYou\" }}. Please click to the following link to get an email to reset your password!"); + .ShouldBe(ForgotPasswordEmailEnglishContent); } } } diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs index c72082945b..d641969f9a 100644 --- a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs +++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo/Abp/Ui/Navigation/MenuManager_Tests.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using NSubstitute; using Shouldly; +using Volo.Abp.Authorization.Permissions; using Volo.Abp.Security.Claims; using Volo.Abp.Testing; using Xunit; @@ -73,8 +74,8 @@ namespace Volo.Abp.UI.Navigation var administration = context.Menu.GetAdministration(); - administration.AddItem(new ApplicationMenuItem("Administration.UserManagement", "User Management", url: "/admin/users", requiredPermissionName: "Administration.UserManagement")); - administration.AddItem(new ApplicationMenuItem("Administration.RoleManagement", "Role Management", url: "/admin/roles", requiredPermissionName: "Administration.RoleManagement")); + administration.AddItem(new ApplicationMenuItem("Administration.UserManagement", "User Management", url: "/admin/users").RequirePermissions("Administration.UserManagement")); + administration.AddItem(new ApplicationMenuItem("Administration.RoleManagement", "Role Management", url: "/admin/roles").RequirePermissions("Administration.RoleManagement")); return Task.CompletedTask; } @@ -94,16 +95,16 @@ namespace Volo.Abp.UI.Navigation return Task.CompletedTask; } - context.Menu.Items.Insert(0, new ApplicationMenuItem("Dashboard", "Dashboard", url: "/dashboard", requiredPermissionName: "Dashboard")); + context.Menu.Items.Insert(0, new ApplicationMenuItem("Dashboard", "Dashboard", url: "/dashboard").RequirePermissions("Dashboard")); var administration = context.Menu.GetAdministration(); - administration.AddItem(new ApplicationMenuItem("Administration.DashboardSettings", "Dashboard Settings", url: "/admin/settings/dashboard", requiredPermissionName: "Administration.DashboardSettings")); + administration.AddItem(new ApplicationMenuItem("Administration.DashboardSettings", "Dashboard Settings", url: "/admin/settings/dashboard").RequirePermissions("Administration.DashboardSettings")); administration.AddItem( new ApplicationMenuItem("Administration.SubMenu1", "Sub menu 1", url: "/submenu1") - .AddItem(new ApplicationMenuItem("Administration.SubMenu1.1", "Sub menu 1.1", url: "/submenu1/submenu1_1", requiredPermissionName: "Administration.SubMenu1.1")) - .AddItem(new ApplicationMenuItem("Administration.SubMenu1.2", "Sub menu 1.2", url: "/submenu1/submenu1_2", requiredPermissionName: "Administration.SubMenu1.2")) + .AddItem(new ApplicationMenuItem("Administration.SubMenu1.1", "Sub menu 1.1", url: "/submenu1/submenu1_1").RequirePermissions("Administration.SubMenu1.1")) + .AddItem(new ApplicationMenuItem("Administration.SubMenu1.2", "Sub menu 1.2", url: "/submenu1/submenu1_2").RequirePermissions("Administration.SubMenu1.2")) ); return Task.CompletedTask; diff --git a/modules/account/Volo.Abp.Account.abpmdl.json b/modules/account/Volo.Abp.Account.abpmdl.json new file mode 100644 index 0000000000..28927ae184 --- /dev/null +++ b/modules/account/Volo.Abp.Account.abpmdl.json @@ -0,0 +1,42 @@ +{ + "folders": { + "items": { + "src": {}, + "test": {} + } + }, + "packages": { + "Volo.Abp.Account.Web": { + "path": "src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.abppkg.json", + "folder": "src" + }, + "Volo.Abp.Account.Web.IdentityServer": { + "path": "src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.abppkg.json", + "folder": "src" + }, + "Volo.Abp.Account.Application": { + "path": "src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.abppkg.json", + "folder": "src" + }, + "Volo.Abp.Account.Application.Contracts": { + "path": "src/Volo.Abp.Account.Application.Contracts/Volo.Abp.Account.Application.Contracts.abppkg.json", + "folder": "src" + }, + "Volo.Abp.Account.HttpApi": { + "path": "src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.abppkg.json", + "folder": "src" + }, + "Volo.Abp.Account.HttpApi.Client": { + "path": "src/Volo.Abp.Account.HttpApi.Client/Volo.Abp.Account.HttpApi.Client.abppkg.json", + "folder": "src" + }, + "Volo.Abp.Account.Application.Tests": { + "path": "test/Volo.Abp.Account.Application.Tests/Volo.Abp.Account.Application.Tests.abppkg.json", + "folder": "test" + }, + "Volo.Abp.Account.Blazor": { + "path": "src/Volo.Abp.Account.Blazor/Volo.Abp.Account.Blazor.abppkg.json", + "folder": "src" + } + } +} \ No newline at end of file diff --git a/modules/account/Volo.Abp.Account.abpsln.json b/modules/account/Volo.Abp.Account.abpsln.json new file mode 100644 index 0000000000..7a1b7818a9 --- /dev/null +++ b/modules/account/Volo.Abp.Account.abpsln.json @@ -0,0 +1,7 @@ +{ + "modules": { + "Volo.Abp.Account": { + "path": "Volo.Abp.Account.abpmdl.json" + } + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo.Abp.Account.Application.Contracts.abppkg.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo.Abp.Account.Application.Contracts.abppkg.json new file mode 100644 index 0000000000..49032794e2 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo.Abp.Account.Application.Contracts.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.application-contracts" +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fi.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fi.json new file mode 100644 index 0000000000..9b4a2ff5df --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fi.json @@ -0,0 +1,67 @@ +{ + "culture": "fi", + "texts": { + "UserName": "Käyttäjätunnus", + "EmailAddress": "Sähköpostiosoite", + "UserNameOrEmailAddress": "Käyttäjänimi tai Sähköpostiosoite", + "Password": "Salasana", + "RememberMe": "Muista minut", + "UseAnotherServiceToLogin": "Käytä toista palvelua kirjautumiseen", + "UserLockedOutMessage": "Käyttäjätili on lukittu virheellisten kirjautumisyritysten vuoksi. Odota hetki ja yritä uudelleen.", + "InvalidUserNameOrPassword": "Väärä käyttäjänimi tai salasana!", + "LoginIsNotAllowed": "Et saa kirjautua sisään! Sinun on vahvistettava sähköpostiosoitteesi / puhelinnumerosi.", + "SelfRegistrationDisabledMessage": "Itserekisteröinti on poistettu käytöstä tälle sovellukselle. Rekisteröi uusi käyttäjä ottamalla yhteyttä sovelluksen järjestelmänvalvojaan.", + "LocalLoginDisabledMessage": "Paikallinen sisäänkirjautuminen on poistettu käytöstä tälle sovellukselle.", + "Login": "Kirjaudu sisään", + "Cancel": "Peruuttaa", + "Register": "Rekisteröidy", + "AreYouANewUser": "Oletko uusi käyttäjä?", + "AlreadyRegistered": "Jo rekisteröity?", + "InvalidLoginRequest": "Virheellinen kirjautumispyyntö", + "ThereAreNoLoginSchemesConfiguredForThisClient": "Tälle asiakkaalle ei ole määritetty kirjautumismalleja.", + "LogInUsingYourProviderAccount": "Kirjaudu sisään {0} -tililläsi", + "DisplayName:CurrentPassword": "Nykyinen salasana", + "DisplayName:NewPassword": "Uusi salasana", + "DisplayName:NewPasswordConfirm": "Vahvista uusi salasana", + "PasswordChangedMessage": "Salasanasi on vaihdettu onnistuneesti.", + "DisplayName:UserName": "Käyttäjätunnus", + "DisplayName:Email": "Sähköposti", + "DisplayName:Name": "Nimi", + "DisplayName:Surname": "Sukunimi", + "DisplayName:Password": "Salasana", + "DisplayName:EmailAddress": "Sähköpostiosoite", + "DisplayName:PhoneNumber": "Puhelinnumero", + "PersonalSettings": "Henkilökohtaiset asetukset", + "PersonalSettingsSaved": "Henkilökohtaiset asetukset tallennettu", + "PasswordChanged": "Salasana vaihdettu", + "NewPasswordConfirmFailed": "Vahvista uusi salasana.", + "Manage": "Hallitse", + "ManageYourProfile": "Hallitse profiiliasi", + "DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Onko itserekisteröinti käytössä", + "Description:Abp.Account.IsSelfRegistrationEnabled": "Voiko käyttäjä rekisteröidä tilin itse.", + "DisplayName:Abp.Account.EnableLocalLogin": "Todennus paikallisella tilillä", + "Description:Abp.Account.EnableLocalLogin": "Ilmaisee, salliko palvelin käyttäjien todentamisen paikallisella tilillä.", + "LoggedOutTitle": "Kirjautui ulos", + "LoggedOutText": "Sinut on kirjautunut ulos ja sinut ohjataan pian.", + "ReturnToText": "Napsauta tätä ja ohjaa uudelleen osoitteeseen {0}", + "OrLoginWith": "Tai kirjaudu sisään:", + "ForgotPassword": "Unohtuiko salasana?", + "SendPasswordResetLink_Information": "Salasanan vaihtamislinkki lähetetään sähköpostiisi salasanan vaihtamiseksi. Jos et saa sähköpostia muutamassa minuutissa, yritä uudelleen.", + "PasswordResetMailSentMessage": "Tilin palauttamisen sähköposti lähetetään sähköpostiosoitteeseesi. Jos et näe tätä sähköpostia postilaatikossa 15 minuutin kuluessa, etsi se roskapostikansiostasi. Jos löydät sen sieltä, merkitse se nimellä -Ei roskaa.", + "ResetPassword": "Nollaa salasana", + "ConfirmPassword": "Vahvista (toista) salasana", + "ResetPassword_Information": "Anna uusi salasanasi.", + "YourPasswordIsSuccessfullyReset": "Salasanasi on palautettu.", + "GoToTheApplication": "Siirry sovellukseen", + "BackToLogin": "Takaisin sisäänkirjautumiseen", + "ProfileTab:Password": "Vaihda salasana", + "ProfileTab:PersonalInfo": "Henkilökohtaiset tiedot", + "ReturnToApplication": "Palaa sovellukseen", + "Volo.Account:InvalidEmailAddress": "Annettua sähköpostiosoitetta ei löydy: {0}", + "PasswordReset": "Salasanan nollaus", + "PasswordResetInfoInEmail": "Saimme tilin palautuspyynnön! Jos aloitit tämän pyynnön, voit nollata salasanasi napsauttamalla seuraavaa linkkiä.", + "ResetMyPassword": "Vaihda salasanani", + "AccessDenied": "Pääsy evätty!", + "AccessDeniedMessage": "Sinulla ei ole pääsyä tähän resurssiin." + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json index 1469c7619d..eb42bbaa0d 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/fr.json @@ -1,6 +1,6 @@ { - "culture": "fr", - "texts": { + "culture": "fr", + "texts": { "UserName": "Nom d'utilisateur", "EmailAddress": "Adresse e-mail", "UserNameOrEmailAddress": "Nom d'utilisateur ou adresse e-mail", @@ -11,50 +11,57 @@ "InvalidUserNameOrPassword": "Nom d'utilisateur ou mot de passe invalide!", "LoginIsNotAllowed": "Vous n'êtes pas autorisé à vous connecter! Vous devez confirmer votre e-mail / numéro de téléphone.", "SelfRegistrationDisabledMessage": "L'auto-inscription est désactivée pour cette application. Veuillez contacter l'administrateur de l'application pour enregistrer un nouvel utilisateur.", - "LocalLoginDisabledMessage": "La connexion locale est désactivée pour cette application.", - "Login": "Connectez-vous", - "Cancel": "Annuler", - "Register": "S'inscrire", - "AreYouANewUser": "Êtes-vous un nouvel utilisateur?", - "AlreadyRegistered": "Déjà inscrit?", - "InvalidLoginRequest": "Demande de connexion non valide", - "ThereAreNoLoginSchemesConfiguredForThisClient": "Aucun schéma de connexion n'est configuré pour ce client.", - "LogInUsingYourProviderAccount": "Connectez-vous à l'aide de votre compte {0}", - "DisplayName:CurrentPassword": "Mot de passe actuel", - "DisplayName:NewPassword": "Nouveau mot de passe", - "DisplayName:NewPasswordConfirm": "Confirmer le nouveau mot de passe", - "PasswordChangedMessage": "Votre mot de passe a été changé avec succès.", - "DisplayName:UserName": "Nom d'utilisateur", - "DisplayName:Email": "Email", - "DisplayName:Name": "Nom", - "DisplayName:Surname": "Nom de famille", - "DisplayName:Password": "Mot de passe", - "DisplayName:EmailAddress": "Adresse e-mail", - "DisplayName:PhoneNumber": "Numéro de téléphone", - "PersonalSettings": "Paramètres personnels", - "PersonalSettingsSaved": "Paramètres personnels enregistrés", - "PasswordChanged": "Mot de passe changé", - "NewPasswordConfirmFailed": "Veuillez confirmer le nouveau mot de passe.", - "Manage": "Gérer", - "ManageYourProfile": "Gérez votre profil", - "DisplayName:Abp.Account.IsSelfRegistrationEnabled": "L’auto-inscription est-elle activée", - "Description:Abp.Account.IsSelfRegistrationEnabled": "Si un utilisateur peut enregistrer le compte par lui-même.", - "DisplayName:Abp.Account.EnableLocalLogin": "Authentifier avec un compte local", - "Description:Abp.Account.EnableLocalLogin": "Indique si le serveur permettra aux utilisateurs de s’authentifier avec un compte local.", - "LoggedOutTitle": "Se déconnecter", - "LoggedOutText": "Vous avez été déconnecté et vous serez bientôt redirigé.", - "ReturnToText": "Cliquez ici pour rediriger vers {0}", - "OrLoginWith": "Ou connectez-vous avec:", - "ForgotPassword": "Vous avez oublié le mot de passe ?", - "SendPasswordResetLink_Information": "Un lien de réinitialisation du mot de passe sera envoyé à votre adresse e-mail pour réinitialiser votre mot de passe. Si vous ne recevez pas d'e-mail dans quelques minutes, veuillez réessayer.", - "PasswordResetMailSentMessage": "E-mail de récupération de compte envoyé à votre adresse e-mail. Si vous ne voyez pas cet e-mail dans votre boîte de réception dans les 15 minutes, recherchez-le dans votre dossier de courrier indésirable. Si vous le trouvez là-bas, veuillez le marquer comme -Pas indésirable-.", - "ResetPassword": "Réinitialiser le mot de passe", - "ConfirmPassword": "Confirmer (répéter) le mot de passe", - "ResetPassword_Information": "Entrez votre nouveau mot de passe.", - "YourPasswordIsSuccessfullyReset": "Votre mot de passe a été réinitialisé avec succès.", - "GoToTheApplication": "Accédez à l’application", - "BackToLogin": "Retour à la connexion", - "ProfileTab:Password": "Changer le mot de passe", - "ProfileTab:PersonalInfo": "Informations personnelles" - } -} + "LocalLoginDisabledMessage": "La connexion locale est désactivée pour cette application.", + "Login": "Connectez-vous", + "Cancel": "Annuler", + "Register": "S'inscrire", + "AreYouANewUser": "Êtes-vous un nouvel utilisateur?", + "AlreadyRegistered": "Déjà inscrit?", + "InvalidLoginRequest": "Demande de connexion non valide", + "ThereAreNoLoginSchemesConfiguredForThisClient": "Aucun schéma de connexion n'est configuré pour ce client.", + "LogInUsingYourProviderAccount": "Connectez-vous à l'aide de votre compte {0}", + "DisplayName:CurrentPassword": "Mot de passe actuel", + "DisplayName:NewPassword": "Nouveau mot de passe", + "DisplayName:NewPasswordConfirm": "Confirmer le nouveau mot de passe", + "PasswordChangedMessage": "Votre mot de passe a été changé avec succès.", + "DisplayName:UserName": "Nom d'utilisateur", + "DisplayName:Email": "Email", + "DisplayName:Name": "Nom", + "DisplayName:Surname": "Nom de famille", + "DisplayName:Password": "Mot de passe", + "DisplayName:EmailAddress": "Adresse e-mail", + "DisplayName:PhoneNumber": "Numéro de téléphone", + "PersonalSettings": "Paramètres personnels", + "PersonalSettingsSaved": "Paramètres personnels enregistrés", + "PasswordChanged": "Mot de passe changé", + "NewPasswordConfirmFailed": "Veuillez confirmer le nouveau mot de passe.", + "Manage": "Gérer", + "ManageYourProfile": "Gérez votre profil", + "DisplayName:Abp.Account.IsSelfRegistrationEnabled": "L’auto-inscription est-elle activée", + "Description:Abp.Account.IsSelfRegistrationEnabled": "Si un utilisateur peut enregistrer le compte par lui-même.", + "DisplayName:Abp.Account.EnableLocalLogin": "Authentifier avec un compte local", + "Description:Abp.Account.EnableLocalLogin": "Indique si le serveur permettra aux utilisateurs de s’authentifier avec un compte local.", + "LoggedOutTitle": "Se déconnecter", + "LoggedOutText": "Vous avez été déconnecté et vous serez bientôt redirigé.", + "ReturnToText": "Cliquez ici pour rediriger vers {0}", + "OrLoginWith": "Ou connectez-vous avec:", + "ForgotPassword": "Vous avez oublié le mot de passe ?", + "SendPasswordResetLink_Information": "Un lien de réinitialisation du mot de passe sera envoyé à votre adresse e-mail pour réinitialiser votre mot de passe. Si vous ne recevez pas d'e-mail dans quelques minutes, veuillez réessayer.", + "PasswordResetMailSentMessage": "E-mail de récupération de compte envoyé à votre adresse e-mail. Si vous ne voyez pas cet e-mail dans votre boîte de réception dans les 15 minutes, recherchez-le dans votre dossier de courrier indésirable. Si vous le trouvez là-bas, veuillez le marquer comme -Pas indésirable-.", + "ResetPassword": "Réinitialiser le mot de passe", + "ConfirmPassword": "Confirmer (répéter) le mot de passe", + "ResetPassword_Information": "Entrez votre nouveau mot de passe.", + "YourPasswordIsSuccessfullyReset": "Votre mot de passe a été réinitialisé avec succès.", + "GoToTheApplication": "Accédez à l’application", + "BackToLogin": "Retour à la connexion", + "ProfileTab:Password": "Changer le mot de passe", + "ProfileTab:PersonalInfo": "Informations personnelles", + "ReturnToApplication": "Revenir à l'application", + "Volo.Account:InvalidEmailAddress": "Impossible de trouver l'adresse e-mail indiquée: {0}", + "PasswordReset": "Réinitialisation du mot de passe", + "PasswordResetInfoInEmail": "Nous avons reçu une demande de récupération de compte! Si vous avez lancé cette demande, cliquez sur le lien suivant pour réinitialiser votre mot de passe.", + "ResetMyPassword": "Réinitialiser mon mot de passe", + "AccessDenied": "Accès refusé!", + "AccessDeniedMessage": "Vous n'avez pas accès à cette ressource." + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hi.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hi.json new file mode 100644 index 0000000000..66c31cf9fb --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hi.json @@ -0,0 +1,67 @@ +{ + "culture": "hi", + "texts": { + "UserName": "उपयोगकर्ता नाम", + "EmailAddress": "ईमेल पता", + "UserNameOrEmailAddress": "उपयोगकर्ता का नाम या ईमेल पता", + "Password": "कुंजिका", + "RememberMe": "मुझे याद रखना", + "UseAnotherServiceToLogin": "लॉग इन करने के लिए किसी अन्य सेवा का उपयोग करें", + "UserLockedOutMessage": "अमान्य लॉगिन प्रयासों के कारण उपयोगकर्ता खाता बंद कर दिया गया है। कृपया थोड़ी देर प्रतीक्षा करें और पुन: प्रयास करें।", + "InvalidUserNameOrPassword": "अमान्य उपयोगकर्ता नाम या पासवर्ड!", + "LoginIsNotAllowed": "आपको लॉगिन करने की अनुमति नहीं है! आपको अपने ईमेल / फोन नंबर की पुष्टि करनी होगी।", + "SelfRegistrationDisabledMessage": "इस आवेदन के लिए स्व-पंजीकरण अक्षम है। नया उपयोगकर्ता पंजीकृत करने के लिए कृपया एप्लिकेशन व्यवस्थापक से संपर्क करें।", + "LocalLoginDisabledMessage": "इस एप्लिकेशन के लिए स्थानीय लॉगिन अक्षम है।", + "Login": "लॉग इन करें", + "Cancel": "रद्द करना", + "Register": "रजिस्टर करें", + "AreYouANewUser": "क्या आप नए उपयोगकर्ता हैं?", + "AlreadyRegistered": "पहले से पंजीकृत?", + "InvalidLoginRequest": "अमान्य लॉगिन अनुरोध", + "ThereAreNoLoginSchemesConfiguredForThisClient": "इस क्लाइंट के लिए कोई लॉगिन योजनाएँ कॉन्फ़िगर नहीं की गई हैं।", + "LogInUsingYourProviderAccount": "अपने {0} खाते का उपयोग करके लॉग इन करें", + "DisplayName:CurrentPassword": "वर्तमान पासवर्ड", + "DisplayName:NewPassword": "नया पासवर्ड", + "DisplayName:NewPasswordConfirm": "नए पासवर्ड की पुष्टि करें", + "PasswordChangedMessage": "तुम्हारा पासवर्ड सफलतापूर्वक बदल दिया गया है।", + "DisplayName:UserName": "उपयोगकर्ता नाम", + "DisplayName:Email": "ईमेल", + "DisplayName:Name": "नाम", + "DisplayName:Surname": "उपनाम", + "DisplayName:Password": "कुंजिका", + "DisplayName:EmailAddress": "ईमेल पता", + "DisplayName:PhoneNumber": "फ़ोन नंबर", + "PersonalSettings": "व्यक्तिगत सेटिंग", + "PersonalSettingsSaved": "व्यक्तिगत सेटिंग्स सहेजे गए", + "PasswordChanged": "पासवर्ड बदला गया", + "NewPasswordConfirmFailed": "कृपया नए पासवर्ड की पुष्टि करें।", + "Manage": "प्रबंधित", + "ManageYourProfile": "अपनी प्रोफ़ाइल प्रबंधित करें", + "DisplayName:Abp.Account.IsSelfRegistrationEnabled": "क्या स्व-पंजीकरण सक्षम है", + "Description:Abp.Account.IsSelfRegistrationEnabled": "उपयोगकर्ता चाहे तो स्वयं या अपने द्वारा खाता पंजीकृत कर सकता है।", + "DisplayName:Abp.Account.EnableLocalLogin": "एक स्थानीय खाते के साथ प्रमाणीकरण", + "Description:Abp.Account.EnableLocalLogin": "इंगित करता है कि सर्वर उपयोगकर्ताओं को स्थानीय खाते से प्रमाणित करने की अनुमति देगा।", + "LoggedOutTitle": "साइन आउट", + "LoggedOutText": "आपको साइन आउट कर दिया गया है और जल्द ही आपको पुनः निर्देशित किया जाएगा।", + "ReturnToText": "{0} पर पुनर्निर्देशित करने के लिए यहां क्लिक करें", + "OrLoginWith": "या इसके साथ लॉगिन करें:", + "ForgotPassword": "पासवर्ड भूल गए?", + "SendPasswordResetLink_Information": "पासवर्ड रीसेट करने के लिए आपके ईमेल पर एक पासवर्ड रीसेट लिंक भेजा जाएगा। यदि आपको कुछ मिनटों के भीतर ईमेल नहीं मिलता है, तो कृपया पुनः प्रयास करें।", + "PasswordResetMailSentMessage": "खाता पुनर्प्राप्ति ईमेल आपके ई-मेल पते पर भेजी जाती है। यदि आप 15 मिनट के भीतर अपने इनबॉक्स में यह ईमेल नहीं देखते हैं, तो इसे अपने जंक मेल फ़ोल्डर में देखें। यदि आप इसे वहां पाते हैं, तो कृपया इसे चिह्नित करें -नहीं जोड़-।", + "ResetPassword": "पासवर्ड रीसेट", + "ConfirmPassword": "पासवर्ड की पुष्टि करें (दोहराएं)", + "ResetPassword_Information": "कृपया अपना नया पासवर्ड दर्ज करें।", + "YourPasswordIsSuccessfullyReset": "आपका पासवर्ड सफलतापूर्वक रीसेट हो गया है।", + "GoToTheApplication": "एप्लिकेशन पर जाएं", + "BackToLogin": "लॉगिन पर वापस जाएं", + "ProfileTab:Password": "पासवर्ड बदलें", + "ProfileTab:PersonalInfo": "व्यक्तिगत जानकारी", + "ReturnToApplication": "आवेदन पर लौटें", + "Volo.Account:InvalidEmailAddress": "दिए गए ईमेल पते को नहीं पा सकते हैं: {0}", + "PasswordReset": "पासवर्ड रीसेट", + "PasswordResetInfoInEmail": "हमें एक खाता पुनर्प्राप्ति अनुरोध प्राप्त हुआ! यदि आपने यह अनुरोध किया है, तो अपना पासवर्ड रीसेट करने के लिए निम्न लिंक पर क्लिक करें।", + "ResetMyPassword": "अपना पासवर्ड रीसेट करें", + "AccessDenied": "पहुंच अस्वीकृत!", + "AccessDeniedMessage": "आपके पास इस संसाधन तक पहुँच नहीं है।" + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/it.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/it.json new file mode 100644 index 0000000000..81f781192d --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/it.json @@ -0,0 +1,67 @@ +{ + "culture": "it", + "texts": { + "UserName": "Nome utente", + "EmailAddress": "Indirizzo e-mail", + "UserNameOrEmailAddress": "Username o Indirizzo Email", + "Password": "Parola d'ordine", + "RememberMe": "Ricordati di me", + "UseAnotherServiceToLogin": "Usa un altro servizio per accedere", + "UserLockedOutMessage": "L'account utente è stato bloccato a causa di tentativi di accesso non validi. Attendi qualche istante e riprova.", + "InvalidUserNameOrPassword": "Username o password non validi!", + "LoginIsNotAllowed": "Non sei autorizzato ad accedere! Devi confermare la tua email / numero di telefono.", + "SelfRegistrationDisabledMessage": "L'auto-registrazione è disabilitata per questa applicazione. Contatta l'amministratore dell'applicazione per registrare un nuovo utente.", + "LocalLoginDisabledMessage": "L'accesso locale è disabilitato per questa applicazione.", + "Login": "Login", + "Cancel": "Annulla", + "Register": "Registrati", + "AreYouANewUser": "Sei un nuovo utente?", + "AlreadyRegistered": "Già registrato?", + "InvalidLoginRequest": "Richiesta di accesso non valida", + "ThereAreNoLoginSchemesConfiguredForThisClient": "Non ci sono schemi di accesso configurati per questo client.", + "LogInUsingYourProviderAccount": "Accedi utilizzando il tuo account {0}", + "DisplayName:CurrentPassword": "Password attuale", + "DisplayName:NewPassword": "Nuova password", + "DisplayName:NewPasswordConfirm": "Conferma la nuova password", + "PasswordChangedMessage": "La tua password è stata cambiata con successo.", + "DisplayName:UserName": "Nome utente", + "DisplayName:Email": "E-mail", + "DisplayName:Name": "Nome", + "DisplayName:Surname": "Cognome", + "DisplayName:Password": "Parola d'ordine", + "DisplayName:EmailAddress": "Indirizzo e-mail", + "DisplayName:PhoneNumber": "Numero di telefono", + "PersonalSettings": "Impostazioni personali", + "PersonalSettingsSaved": "Impostazioni personali salvate", + "PasswordChanged": "Password cambiata", + "NewPasswordConfirmFailed": "Conferma la nuova password.", + "Manage": "Gestire", + "ManageYourProfile": "Gestisci il tuo profilo", + "DisplayName:Abp.Account.IsSelfRegistrationEnabled": "L'auto-registrazione è abilitata", + "Description:Abp.Account.IsSelfRegistrationEnabled": "Se un utente può registrare l'account da solo.", + "DisplayName:Abp.Account.EnableLocalLogin": "Autentica con un account locale", + "Description:Abp.Account.EnableLocalLogin": "Indica se il server consentirà agli utenti di autenticarsi con un account locale.", + "LoggedOutTitle": "Disconnesso", + "LoggedOutText": "Sei stato disconnesso e verrai reindirizzato presto.", + "ReturnToText": "Fai clic qui per reindirizzare a {0}", + "OrLoginWith": "Oppure accedi con:", + "ForgotPassword": "Ha dimenticato la password?", + "SendPasswordResetLink_Information": "Un link per reimpostare la password verrà inviato alla tua e-mail per reimpostare la password. Se non ricevi un'email entro pochi minuti, riprova.", + "PasswordResetMailSentMessage": "E-mail di recupero dell'account inviata al tuo indirizzo e-mail. Se non vedi questa email nella tua posta in arrivo entro 15 minuti, cercala nella cartella della posta indesiderata. Se lo trovi lì, contrassegnalo come -Non Junk-.", + "ResetPassword": "Resetta la password", + "ConfirmPassword": "Conferma (ripeti) la password", + "ResetPassword_Information": "Per favore inserisci la tua nuova password.", + "YourPasswordIsSuccessfullyReset": "La tua password è stata reimpostata con successo.", + "GoToTheApplication": "Vai all'applicazione", + "BackToLogin": "Torna al login", + "ProfileTab:Password": "Cambia la password", + "ProfileTab:PersonalInfo": "Informazioni personali", + "ReturnToApplication": "Torna all'applicazione", + "Volo.Account:InvalidEmailAddress": "Impossibile trovare l'indirizzo email fornito: {0}", + "PasswordReset": "Reimpostazione della password", + "PasswordResetInfoInEmail": "Abbiamo ricevuto una richiesta di recupero dell'account! Se hai avviato questa richiesta, fai clic sul seguente collegamento per reimpostare la password.", + "ResetMyPassword": "Reimposta la mia password", + "AccessDenied": "Accesso negato!", + "AccessDeniedMessage": "Non hai accesso a questa risorsa." + } +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json index efd751859e..7b17f1076b 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/nl.json @@ -60,6 +60,8 @@ "Volo.Account:InvalidEmailAddress": "Kan het opgegeven e-mailadres '{0}' niet vinden", "PasswordReset": "Wachtwoord opnieuw instellen", "PasswordResetInfoInEmail": "We hebben een verzoek ontvangen om uw wachtwoord opnieuw in te stellen. Als u dit verzoek heeft ingediend, klikt u op de volgende link om een nieuw wachtwoord in te stellen.", - "ResetMyPassword": "Reset mijn wachtwoord" + "ResetMyPassword": "Reset mijn wachtwoord", + "AccessDenied": "Toegang geweigerd!", + "AccessDeniedMessage": "U heeft geen toegang tot deze bron." } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.abppkg.json b/modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.abppkg.json new file mode 100644 index 0000000000..412567ac33 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.application" +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Blazor/Volo.Abp.Account.Blazor.abppkg.json b/modules/account/src/Volo.Abp.Account.Blazor/Volo.Abp.Account.Blazor.abppkg.json new file mode 100644 index 0000000000..19c29b7b8b --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Blazor/Volo.Abp.Account.Blazor.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.blazor" +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.HttpApi.Client/Volo.Abp.Account.HttpApi.Client.abppkg.json b/modules/account/src/Volo.Abp.Account.HttpApi.Client/Volo.Abp.Account.HttpApi.Client.abppkg.json new file mode 100644 index 0000000000..7deef5e383 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.HttpApi.Client/Volo.Abp.Account.HttpApi.Client.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.http-api-client" +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.abppkg.json b/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.abppkg.json new file mode 100644 index 0000000000..515bfe64c4 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.http-api" +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs index 4dab1f9761..2bdadc6ebd 100644 --- a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs +++ b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs @@ -189,46 +189,32 @@ namespace Volo.Abp.Account.Web.Pages.Account return await base.OnPostExternalLogin(provider); } - private async Task ProcessWindowsLoginAsync() + protected virtual async Task ProcessWindowsLoginAsync() { var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName); - if (!(result?.Principal is WindowsPrincipal windowsPrincipal)) + if (result.Succeeded) { - return Challenge(AccountOptions.WindowsAuthenticationSchemeName); - } - - var props = new AuthenticationProperties - { - RedirectUri = Url.Page("./Login", pageHandler: "ExternalLoginCallback", values: new { ReturnUrl, ReturnUrlHash }), - Items = + var props = new AuthenticationProperties() { - {"scheme", AccountOptions.WindowsAuthenticationSchemeName}, - } - }; - - var identity = new ClaimsIdentity(AccountOptions.WindowsAuthenticationSchemeName); - identity.AddClaim(new Claim(JwtClaimTypes.Subject, windowsPrincipal.Identity.Name)); - identity.AddClaim(new Claim(JwtClaimTypes.Name, windowsPrincipal.Identity.Name)); - - //TODO: Consider to add Windows groups the the identity - //if (_accountOptions.IncludeWindowsGroups) - //{ - // var windowsIdentity = windowsPrincipal.Identity as WindowsIdentity; - // if (windowsIdentity != null) - // { - // var groups = windowsIdentity.Groups?.Translate(typeof(NTAccount)); - // var roles = groups.Select(x => new Claim(JwtClaimTypes.Role, x.Value)); - // identity.AddClaims(roles); - // } - //} - - await HttpContext.SignInAsync( - IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme, - new ClaimsPrincipal(identity), - props - ); + RedirectUri = Url.Page("./Login", pageHandler: "ExternalLoginCallback", values: new {ReturnUrl, ReturnUrlHash}), + Items = + { + { + "LoginProvider", AccountOptions.WindowsAuthenticationSchemeName + }, + } + }; + + var id = new ClaimsIdentity(AccountOptions.WindowsAuthenticationSchemeName); + id.AddClaim(new Claim(ClaimTypes.NameIdentifier, result.Principal.FindFirstValue(ClaimTypes.PrimarySid))); + id.AddClaim(new Claim(ClaimTypes.Name, result.Principal.FindFirstValue(ClaimTypes.Name))); + + await HttpContext.SignInAsync(IdentityConstants.ExternalScheme, new ClaimsPrincipal(id), props); + + return Redirect(props.RedirectUri); + } - return RedirectSafely(props.RedirectUri); + return Challenge(AccountOptions.WindowsAuthenticationSchemeName); } } } diff --git a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.abppkg.json b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.abppkg.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.abppkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.abppkg.json b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.abppkg.json new file mode 100644 index 0000000000..930c4018b3 --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.mvc" +} \ No newline at end of file diff --git a/modules/account/test/Volo.Abp.Account.Application.Tests/Volo.Abp.Account.Application.Tests.abppkg.json b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo.Abp.Account.Application.Tests.abppkg.json new file mode 100644 index 0000000000..a686451fbc --- /dev/null +++ b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo.Abp.Account.Application.Tests.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.test" +} \ No newline at end of file diff --git a/modules/audit-logging/Volo.Abp.AuditLogging.abpmdl.json b/modules/audit-logging/Volo.Abp.AuditLogging.abpmdl.json new file mode 100644 index 0000000000..5b2cc3f54b --- /dev/null +++ b/modules/audit-logging/Volo.Abp.AuditLogging.abpmdl.json @@ -0,0 +1,42 @@ +{ + "folders": { + "items": { + "src": {}, + "test": {} + } + }, + "packages": { + "Volo.Abp.AuditLogging.Domain.Shared": { + "path": "src/Volo.Abp.AuditLogging.Domain.Shared/Volo.Abp.AuditLogging.Domain.Shared.abppkg.json", + "folder": "src" + }, + "Volo.Abp.AuditLogging.Domain": { + "path": "src/Volo.Abp.AuditLogging.Domain/Volo.Abp.AuditLogging.Domain.abppkg.json", + "folder": "src" + }, + "Volo.Abp.AuditLogging.EntityFrameworkCore": { + "path": "src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.abppkg.json", + "folder": "src" + }, + "Volo.Abp.AuditLogging.MongoDB": { + "path": "src/Volo.Abp.AuditLogging.MongoDB/Volo.Abp.AuditLogging.MongoDB.abppkg.json", + "folder": "src" + }, + "Volo.Abp.AuditLogging.Tests": { + "path": "test/Volo.Abp.AuditLogging.Tests/Volo.Abp.AuditLogging.Tests.abppkg.json", + "folder": "test" + }, + "Volo.Abp.AuditLogging.TestBase": { + "path": "test/Volo.Abp.AuditLogging.TestBase/Volo.Abp.AuditLogging.TestBase.abppkg.json", + "folder": "test" + }, + "Volo.Abp.AuditLogging.EntityFrameworkCore.Tests": { + "path": "test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.abppkg.json", + "folder": "test" + }, + "Volo.Abp.AuditLogging.MongoDB.Tests": { + "path": "test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.abppkg.json", + "folder": "test" + } + } +} \ No newline at end of file diff --git a/modules/audit-logging/Volo.Abp.AuditLogging.abpsln.json b/modules/audit-logging/Volo.Abp.AuditLogging.abpsln.json new file mode 100644 index 0000000000..380c46c413 --- /dev/null +++ b/modules/audit-logging/Volo.Abp.AuditLogging.abpsln.json @@ -0,0 +1,7 @@ +{ + "modules": { + "Volo.Abp.AuditLogging": { + "path": "Volo.Abp.AuditLogging.abpmdl.json" + } + } +} \ No newline at end of file diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo.Abp.AuditLogging.Domain.Shared.abppkg.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo.Abp.AuditLogging.Domain.Shared.abppkg.json new file mode 100644 index 0000000000..8b3de05f76 --- /dev/null +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo.Abp.AuditLogging.Domain.Shared.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.domain-shared" +} \ No newline at end of file diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo.Abp.AuditLogging.Domain.abppkg.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo.Abp.AuditLogging.Domain.abppkg.json new file mode 100644 index 0000000000..1d574efe45 --- /dev/null +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo.Abp.AuditLogging.Domain.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.domain" +} \ No newline at end of file diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.abppkg.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.abppkg.json new file mode 100644 index 0000000000..e1c64f0175 --- /dev/null +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.ef" +} \ No newline at end of file diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo.Abp.AuditLogging.MongoDB.abppkg.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo.Abp.AuditLogging.MongoDB.abppkg.json new file mode 100644 index 0000000000..8b23fd1e69 --- /dev/null +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo.Abp.AuditLogging.MongoDB.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.mongodb" +} \ No newline at end of file diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.abppkg.json b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.abppkg.json new file mode 100644 index 0000000000..a686451fbc --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.test" +} \ No newline at end of file diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.abppkg.json b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.abppkg.json new file mode 100644 index 0000000000..a686451fbc --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.test" +} \ No newline at end of file diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo.Abp.AuditLogging.TestBase.abppkg.json b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo.Abp.AuditLogging.TestBase.abppkg.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo.Abp.AuditLogging.TestBase.abppkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.Tests/Volo.Abp.AuditLogging.Tests.abppkg.json b/modules/audit-logging/test/Volo.Abp.AuditLogging.Tests/Volo.Abp.AuditLogging.Tests.abppkg.json new file mode 100644 index 0000000000..a686451fbc --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.Tests/Volo.Abp.AuditLogging.Tests.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.test" +} \ No newline at end of file diff --git a/modules/background-jobs/Volo.Abp.BackgroundJobs.abpmdl.json b/modules/background-jobs/Volo.Abp.BackgroundJobs.abpmdl.json new file mode 100644 index 0000000000..e3bea65da3 --- /dev/null +++ b/modules/background-jobs/Volo.Abp.BackgroundJobs.abpmdl.json @@ -0,0 +1,63 @@ +{ + "folders": { + "items": { + "src": {}, + "test": {}, + "app": {} + } + }, + "packages": { + "Volo.Abp.BackgroundJobs.Domain.Shared": { + "path": "src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo.Abp.BackgroundJobs.Domain.Shared.abppkg.json", + "folder": "src" + }, + "Volo.Abp.BackgroundJobs.Domain": { + "path": "src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.abppkg.json", + "folder": "src" + }, + "Volo.Abp.BackgroundJobs.EntityFrameworkCore": { + "path": "src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.abppkg.json", + "folder": "src" + }, + "Volo.Abp.BackgroundJobs.MongoDB": { + "path": "src/Volo.Abp.BackgroundJobs.MongoDB/Volo.Abp.BackgroundJobs.MongoDB.abppkg.json", + "folder": "src" + }, + "Volo.Abp.BackgroundJobs.TestBase": { + "path": "test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.abppkg.json", + "folder": "test" + }, + "Volo.Abp.BackgroundJobs.Domain.Tests": { + "path": "test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.abppkg.json", + "folder": "test" + }, + "Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests": { + "path": "test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.abppkg.json", + "folder": "test" + }, + "Volo.Abp.BackgroundJobs.MongoDB.Tests": { + "path": "test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.abppkg.json", + "folder": "test" + }, + "Volo.Abp.BackgroundJobs.DemoApp": { + "path": "app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.abppkg.json", + "folder": "app" + }, + "Volo.Abp.BackgroundJobs.DemoApp.Shared": { + "path": "app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.abppkg.json", + "folder": "app" + }, + "Volo.Abp.BackgroundJobs.DemoApp.HangFire": { + "path": "app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.abppkg.json", + "folder": "app" + }, + "Volo.Abp.BackgroundJobs.DemoApp.RabbitMq": { + "path": "app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq.abppkg.json", + "folder": "app" + }, + "Volo.Abp.BackgroundJobs.DemoApp.Quartz": { + "path": "app/Volo.Abp.BackgroundJobs.DemoApp.Quartz/Volo.Abp.BackgroundJobs.DemoApp.Quartz.abppkg.json", + "folder": "app" + } + } +} \ No newline at end of file diff --git a/modules/background-jobs/Volo.Abp.BackgroundJobs.abpsln.json b/modules/background-jobs/Volo.Abp.BackgroundJobs.abpsln.json new file mode 100644 index 0000000000..08b606ec39 --- /dev/null +++ b/modules/background-jobs/Volo.Abp.BackgroundJobs.abpsln.json @@ -0,0 +1,7 @@ +{ + "modules": { + "Volo.Abp.BackgroundJobs": { + "path": "Volo.Abp.BackgroundJobs.abpmdl.json" + } + } +} \ No newline at end of file diff --git a/modules/background-jobs/Volo.Abp.BackgroundJobs.sln b/modules/background-jobs/Volo.Abp.BackgroundJobs.sln index 83263fa296..771eb08b19 100644 --- a/modules/background-jobs/Volo.Abp.BackgroundJobs.sln +++ b/modules/background-jobs/Volo.Abp.BackgroundJobs.sln @@ -9,7 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundJobs.Dom EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{649A3FFA-182F-4E56-9717-E6A9A2BEC545}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{E400416D-2895-4512-9D17-90681EEC7E0A}" EndProject diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.abppkg.json b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.abppkg.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.abppkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Quartz/Volo.Abp.BackgroundJobs.DemoApp.Quartz.abppkg.json b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Quartz/Volo.Abp.BackgroundJobs.DemoApp.Quartz.abppkg.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Quartz/Volo.Abp.BackgroundJobs.DemoApp.Quartz.abppkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq.abppkg.json b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq.abppkg.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq.abppkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.abppkg.json b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.abppkg.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.abppkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.abppkg.json b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.abppkg.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.abppkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo.Abp.BackgroundJobs.Domain.Shared.abppkg.json b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo.Abp.BackgroundJobs.Domain.Shared.abppkg.json new file mode 100644 index 0000000000..8b3de05f76 --- /dev/null +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo.Abp.BackgroundJobs.Domain.Shared.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.domain-shared" +} \ No newline at end of file diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.abppkg.json b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.abppkg.json new file mode 100644 index 0000000000..1d574efe45 --- /dev/null +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.domain" +} \ No newline at end of file diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.abppkg.json b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.abppkg.json new file mode 100644 index 0000000000..e1c64f0175 --- /dev/null +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.ef" +} \ No newline at end of file diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo.Abp.BackgroundJobs.MongoDB.abppkg.json b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo.Abp.BackgroundJobs.MongoDB.abppkg.json new file mode 100644 index 0000000000..8b23fd1e69 --- /dev/null +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo.Abp.BackgroundJobs.MongoDB.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.mongodb" +} \ No newline at end of file diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.abppkg.json b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.abppkg.json new file mode 100644 index 0000000000..a686451fbc --- /dev/null +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.test" +} \ No newline at end of file diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.abppkg.json b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.abppkg.json new file mode 100644 index 0000000000..a686451fbc --- /dev/null +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.test" +} \ No newline at end of file diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.abppkg.json b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.abppkg.json new file mode 100644 index 0000000000..a686451fbc --- /dev/null +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.test" +} \ No newline at end of file diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.abppkg.json b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.abppkg.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.abppkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/modules/blob-storing-database/Volo.Abp.BlobStoring.Database.abpmdl.json b/modules/blob-storing-database/Volo.Abp.BlobStoring.Database.abpmdl.json new file mode 100644 index 0000000000..f5f118cbdc --- /dev/null +++ b/modules/blob-storing-database/Volo.Abp.BlobStoring.Database.abpmdl.json @@ -0,0 +1,55 @@ +{ + "folders": { + "items": { + "src": {}, + "test": {}, + "host": { + "items": { + "BlobStoring.Database.Host.ConsoleApp": { + "items": { + "src": {} + } + } + } + } + } + }, + "packages": { + "Volo.Abp.BlobStoring.Database.Domain.Shared": { + "path": "src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo.Abp.BlobStoring.Database.Domain.Shared.abppkg.json", + "folder": "src" + }, + "Volo.Abp.BlobStoring.Database.Domain": { + "path": "src/Volo.Abp.BlobStoring.Database.Domain/Volo.Abp.BlobStoring.Database.Domain.abppkg.json", + "folder": "src" + }, + "Volo.Abp.BlobStoring.Database.EntityFrameworkCore": { + "path": "src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.abppkg.json", + "folder": "src" + }, + "Volo.Abp.BlobStoring.Database.MongoDB": { + "path": "src/Volo.Abp.BlobStoring.Database.MongoDB/Volo.Abp.BlobStoring.Database.MongoDB.abppkg.json", + "folder": "src" + }, + "Volo.Abp.BlobStoring.Database.TestBase": { + "path": "test/Volo.Abp.BlobStoring.Database.TestBase/Volo.Abp.BlobStoring.Database.TestBase.abppkg.json", + "folder": "test" + }, + "Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests": { + "path": "test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests.abppkg.json", + "folder": "test" + }, + "Volo.Abp.BlobStoring.Database.MongoDB.Tests": { + "path": "test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.abppkg.json", + "folder": "test" + }, + "Volo.Abp.BlobStoring.Database.Domain.Tests": { + "path": "test/Volo.Abp.BlobStoring.Database.Domain.Tests/Volo.Abp.BlobStoring.Database.Domain.Tests.abppkg.json", + "folder": "test" + }, + "BlobStoring.Database.Host.ConsoleApp.ConsoleApp": { + "path": "host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/BlobStoring.Database.Host.ConsoleApp.ConsoleApp.abppkg.json", + "folder": "host/BlobStoring.Database.Host.ConsoleApp/src" + } + } +} \ No newline at end of file diff --git a/modules/blob-storing-database/Volo.Abp.BlobStoring.Database.abpsln.json b/modules/blob-storing-database/Volo.Abp.BlobStoring.Database.abpsln.json new file mode 100644 index 0000000000..e90f5d10ff --- /dev/null +++ b/modules/blob-storing-database/Volo.Abp.BlobStoring.Database.abpsln.json @@ -0,0 +1,10 @@ +{ + "modules": { + "Volo.Abp.BlobStoring.Database": { + "path": "Volo.Abp.BlobStoring.Database.abpmdl.json" + }, + "BlobStoring.Database.Host.ConsoleApp": { + "path": "host/BlobStoring.Database.Host.ConsoleApp/BlobStoring.Database.Host.ConsoleApp.abpmdl.json" + } + } +} \ No newline at end of file diff --git a/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/BlobStoring.Database.Host.ConsoleApp.abpmdl.json b/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/BlobStoring.Database.Host.ConsoleApp.abpmdl.json new file mode 100644 index 0000000000..e8b2a715c8 --- /dev/null +++ b/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/BlobStoring.Database.Host.ConsoleApp.abpmdl.json @@ -0,0 +1,13 @@ +{ + "folders": { + "items": { + "src": {} + } + }, + "packages": { + "BlobStoring.Database.Host.ConsoleApp.ConsoleApp": { + "path": "src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/BlobStoring.Database.Host.ConsoleApp.ConsoleApp.abppkg.json", + "folder": "src" + } + } +} \ No newline at end of file diff --git a/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/BlobStoring.Database.Host.ConsoleApp.ConsoleApp.abppkg.json b/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/BlobStoring.Database.Host.ConsoleApp.ConsoleApp.abppkg.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/BlobStoring.Database.Host.ConsoleApp.ConsoleApp.abppkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo.Abp.BlobStoring.Database.Domain.Shared.abppkg.json b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo.Abp.BlobStoring.Database.Domain.Shared.abppkg.json new file mode 100644 index 0000000000..8b3de05f76 --- /dev/null +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo.Abp.BlobStoring.Database.Domain.Shared.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.domain-shared" +} \ No newline at end of file diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/fi.json b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/fi.json new file mode 100644 index 0000000000..b2bf5f1fc3 --- /dev/null +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/fi.json @@ -0,0 +1,6 @@ +{ + "culture": "fi", + "texts": { + "ManageYourProfile": "Hallitse profiiliasi" + } +} \ No newline at end of file diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/hi.json b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/hi.json new file mode 100644 index 0000000000..35062bd727 --- /dev/null +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/hi.json @@ -0,0 +1,6 @@ +{ + "culture": "hi", + "texts": { + "ManageYourProfile": "अपनी प्रोफ़ाइल प्रबंधित करें" + } +} \ No newline at end of file diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/it.json b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/it.json new file mode 100644 index 0000000000..d0b87bd9d3 --- /dev/null +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/it.json @@ -0,0 +1,6 @@ +{ + "culture": "it", + "texts": { + "ManageYourProfile": "Gestisci il tuo profilo" + } +} \ No newline at end of file diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo.Abp.BlobStoring.Database.Domain.abppkg.json b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo.Abp.BlobStoring.Database.Domain.abppkg.json new file mode 100644 index 0000000000..1d574efe45 --- /dev/null +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain/Volo.Abp.BlobStoring.Database.Domain.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.domain" +} \ No newline at end of file diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.abppkg.json b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.abppkg.json new file mode 100644 index 0000000000..e1c64f0175 --- /dev/null +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.EntityFrameworkCore/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.ef" +} \ No newline at end of file diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo.Abp.BlobStoring.Database.MongoDB.abppkg.json b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo.Abp.BlobStoring.Database.MongoDB.abppkg.json new file mode 100644 index 0000000000..8b23fd1e69 --- /dev/null +++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.MongoDB/Volo.Abp.BlobStoring.Database.MongoDB.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.mongodb" +} \ No newline at end of file diff --git a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.Domain.Tests/Volo.Abp.BlobStoring.Database.Domain.Tests.abppkg.json b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.Domain.Tests/Volo.Abp.BlobStoring.Database.Domain.Tests.abppkg.json new file mode 100644 index 0000000000..a686451fbc --- /dev/null +++ b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.Domain.Tests/Volo.Abp.BlobStoring.Database.Domain.Tests.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.test" +} \ No newline at end of file diff --git a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests.abppkg.json b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests.abppkg.json new file mode 100644 index 0000000000..a686451fbc --- /dev/null +++ b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.test" +} \ No newline at end of file diff --git a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.abppkg.json b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.abppkg.json new file mode 100644 index 0000000000..a686451fbc --- /dev/null +++ b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.abppkg.json @@ -0,0 +1,3 @@ +{ + "role": "lib.test" +} \ No newline at end of file diff --git a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.TestBase/Volo.Abp.BlobStoring.Database.TestBase.abppkg.json b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.TestBase/Volo.Abp.BlobStoring.Database.TestBase.abppkg.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.TestBase/Volo.Abp.BlobStoring.Database.TestBase.abppkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs index 2a31e4aa74..09bb9ca36b 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs +++ b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs @@ -165,6 +165,7 @@ namespace Volo.BloggingTestApp }); app.UseAuthentication(); + app.UseAuthorization(); app.UseAbpRequestLocalization(); diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ar.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ar.js new file mode 100644 index 0000000000..fe036163c7 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ar.js @@ -0,0 +1,171 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 1); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Arabic + * @author Amira Salah + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage('ar', { + Markdown: 'لغة ترميز', + WYSIWYG: 'ما تراه هو ما تحصل عليه', + Write: 'يكتب', + Preview: 'عرض مسبق', + Headings: 'العناوين', + Paragraph: 'فقرة', + Bold: 'خط عريض', + Italic: 'خط مائل', + Strike: 'إضراب', + Code: 'رمز', + Line: 'خط', + Blockquote: 'فقرة مقتبسة', + 'Unordered list': 'قائمة غير مرتبة', + 'Ordered list': 'قائمة مرتبة', + Task: 'مهمة', + Indent: 'المسافة البادئة', + Outdent: 'المسافة الخارجة', + 'Insert link': 'أدخل الرابط', + 'Insert CodeBlock': 'أدخل الكود', + 'Insert table': 'أدخل جدول', + 'Insert image': 'أدخل صورة', + Heading: 'عنوان', + 'Image URL': 'رابط الصورة', + 'Select image file': 'حدد ملف الصورة', + Description: 'وصف', + OK: 'موافقة', + More: 'أكثر', + Cancel: 'إلغاء', + File: 'ملف', + URL: 'رابط', + 'Link text': 'نص الرابط', + 'Add row': 'ضف سطر', + 'Add col': 'ضف عمود', + 'Remove row': 'حذف سطر', + 'Remove col': 'حذف عمود', + 'Align left': 'محاذاة اليسار', + 'Align center': 'محاذاة الوسط', + 'Align right': 'محاذاة اليمين', + 'Remove table': 'حذف الجدول', + 'Would you like to paste as table?': 'هل تريد اللصق كجدول', + 'Text color': 'لون النص', + 'Auto scroll enabled': 'التحريك التلقائي ممكّن', + 'Auto scroll disabled': 'التحريك التلقائي معطّل', + 'Choose language': 'اختر اللغة' +}); + +/***/ }) +/******/ ]); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/cs-cz.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/cs-cz.js new file mode 100644 index 0000000000..03056d947c --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/cs-cz.js @@ -0,0 +1,172 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 2); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), +/* 1 */, +/* 2 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Czech + * @author Dmitrij Tkačenko + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['cs', 'cs-CZ'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Napsat', + Preview: 'Náhled', + Headings: 'Nadpisy', + Paragraph: 'Odstavec', + Bold: 'Tučné', + Italic: 'Kurzíva', + Strike: 'Přeškrtnuté', + Code: 'Kód', + Line: 'Vodorovná čára', + Blockquote: 'Citace', + 'Unordered list': 'Seznam s odrážkami', + 'Ordered list': 'Číslovaný seznam', + Task: 'Úkol', + Indent: 'Zvětšit odsazení', + Outdent: 'Zmenšit odsazení', + 'Insert link': 'Vložit odkaz', + 'Insert CodeBlock': 'Vložit blok kódu', + 'Insert table': 'Vložit tabulku', + 'Insert image': 'Vložit obrázek', + Heading: 'Nadpis', + 'Image URL': 'URL obrázku', + 'Select image file': 'Vybrat obrázek', + Description: 'Popis', + OK: 'OK', + More: 'Více', + Cancel: 'Zrušit', + File: 'Soubor', + URL: 'URL', + 'Link text': 'Text odkazu', + 'Add row': 'Přidat řádek', + 'Add col': 'Přidat sloupec', + 'Remove row': 'Odebrat řádek', + 'Remove col': 'Odebrat sloupec', + 'Align left': 'Zarovnat vlevo', + 'Align center': 'Zarovnat na střed', + 'Align right': 'Zarovnat vpravo', + 'Remove table': 'Odstranit tabulku', + 'Would you like to paste as table?': 'Chcete vložit jako tabulku?', + 'Text color': 'Barva textu', + 'Auto scroll enabled': 'Automatické rolování zapnuto', + 'Auto scroll disabled': 'Automatické rolování vypnuto', + 'Choose language': 'Vybrat jazyk' +}); + +/***/ }) +/******/ ]); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/de-de.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/de-de.js new file mode 100644 index 0000000000..5f325f3af5 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/de-de.js @@ -0,0 +1,173 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 3); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), +/* 1 */, +/* 2 */, +/* 3 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for German + * @author Jann-Niklas Kiepert + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['de', 'de-DE'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Verfassen', + Preview: 'Vorschau', + Headings: 'Überschriften', + Paragraph: 'Text', + Bold: 'Fett', + Italic: 'Kursiv', + Strike: 'Durchgestrichen', + Code: 'Code', + Line: 'Trennlinie', + Blockquote: 'Blocktext', + 'Unordered list': 'Aufzählung', + 'Ordered list': 'Nummerierte Aufzählung', + Task: 'Aufgabe', + Indent: 'Einrücken', + Outdent: 'Ausrücken', + 'Insert link': 'Link einfügen', + 'Insert CodeBlock': 'Codeblock einfügen', + 'Insert table': 'Tabelle einfügen', + 'Insert image': 'Grafik einfügen', + Heading: 'Titel', + 'Image URL': 'Bild URL', + 'Select image file': 'Grafik auswählen', + Description: 'Beschreibung', + OK: 'OK', + More: 'Mehr', + Cancel: 'Abbrechen', + File: 'Datei', + URL: 'URL', + 'Link text': 'Anzuzeigender Text', + 'Add row': 'Zeile hinzufügen', + 'Add col': 'Spalte hinzufügen', + 'Remove row': 'Zeile entfernen', + 'Remove col': 'Spalte entfernen', + 'Align left': 'Links ausrichten', + 'Align center': 'Zentrieren', + 'Align right': 'Rechts ausrichten', + 'Remove table': 'Tabelle entfernen', + 'Would you like to paste as table?': 'Möchten Sie eine Tabelle einfügen?', + 'Text color': 'Textfarbe', + 'Auto scroll enabled': 'Autoscrollen aktiviert', + 'Auto scroll disabled': 'Autoscrollen deaktiviert', + 'Choose language': 'Sprache auswählen' +}); + +/***/ }) +/******/ ]); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/es-es.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/es-es.js new file mode 100644 index 0000000000..eb76415e73 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/es-es.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 4); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), +/* 1 */, +/* 2 */, +/* 3 */, +/* 4 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Spanish + * @author Enrico Lamperti + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['es', 'es-ES'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Escribir', + Preview: 'Vista previa', + Headings: 'Encabezados', + Paragraph: 'Párrafo', + Bold: 'Negrita', + Italic: 'Itálica', + Strike: 'Tachado', + Code: 'Código', + Line: 'Línea', + Blockquote: 'Cita', + 'Unordered list': 'Lista desordenada', + 'Ordered list': 'Lista ordenada', + Task: 'Tarea', + Indent: 'Sangría', + Outdent: 'Saliendo', + 'Insert link': 'Insertar enlace', + 'Insert CodeBlock': 'Insertar bloque de código', + 'Insert table': 'Insertar tabla', + 'Insert image': 'Insertar imagen', + Heading: 'Encabezado', + 'Image URL': 'URL de la imagen', + 'Select image file': 'Seleccionar archivo de imagen', + Description: 'Descripción', + OK: 'Aceptar', + More: 'Más', + Cancel: 'Cancelar', + File: 'Archivo', + URL: 'URL', + 'Link text': 'Texto del enlace', + 'Add row': 'Agregar fila', + 'Add col': 'Agregar columna', + 'Remove row': 'Eliminar fila', + 'Remove col': 'Eliminar columna', + 'Align left': 'Alinear a la izquierda', + 'Align center': 'Centrar', + 'Align right': 'Alinear a la derecha', + 'Remove table': 'Eliminar tabla', + 'Would you like to paste as table?': '¿Desea pegar como tabla?', + 'Text color': 'Color del texto', + 'Auto scroll enabled': 'Desplazamiento automático habilitado', + 'Auto scroll disabled': 'Desplazamiento automático deshabilitado', + 'Choose language': 'Elegir idioma' +}); + +/***/ }) +/******/ ]); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/fi-fi.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/fi-fi.js new file mode 100644 index 0000000000..89b02e3d55 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/fi-fi.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 5); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 5: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Finnish + * @author Tomi Mynttinen + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['fi', 'fi-FI'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Kirjoita', + Preview: 'Esikatselu', + Headings: 'Otsikot', + Paragraph: 'Kappale', + Bold: 'Lihavointi', + Italic: 'Kursivointi', + Strike: 'Yliviivaus', + Code: 'Koodi', + Line: 'Vaakaviiva', + Blockquote: 'Lainaus', + 'Unordered list': 'Luettelo', + 'Ordered list': 'Numeroitu luettelo', + Task: 'Tehtävä', + Indent: 'Suurenna sisennystä', + Outdent: 'Pienennä sisennystä', + 'Insert link': 'Lisää linkki', + 'Insert CodeBlock': 'Lisää koodia', + 'Insert table': 'Lisää taulukko', + 'Insert image': 'Lisää kuva', + Heading: 'Otsikko', + 'Image URL': 'Kuvan URL', + 'Select image file': 'Valitse kuvatiedosto', + Description: 'Kuvaus', + OK: 'OK', + More: 'Lisää', + Cancel: 'Peruuta', + File: 'Tiedosto', + URL: 'URL', + 'Link text': 'Linkkiteksti', + 'Add row': 'Lisää rivi', + 'Add col': 'Lisää sarake', + 'Remove row': 'Poista rivi', + 'Remove col': 'Poista sarake', + 'Align left': 'Tasaus vasemmalle', + 'Align center': 'Keskitä', + 'Align right': 'Tasaus oikealle', + 'Remove table': 'Poista taulukko', + 'Would you like to paste as table?': 'Haluatko liittää taulukkomuodossa?', + 'Text color': 'Tekstin väri', + 'Auto scroll enabled': 'Automaattinen skrollaus käytössä', + 'Auto scroll disabled': 'Automaattinen skrollaus pois käytöstä', + 'Choose language': 'Valitse kieli' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/fr-fr.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/fr-fr.js new file mode 100644 index 0000000000..59177f18d0 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/fr-fr.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 6); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 6: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for French + * @author Stanislas Michalak + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['fr', 'fr-FR'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Écrire', + Preview: 'Aperçu', + Headings: 'En-têtes', + Paragraph: 'Paragraphe', + Bold: 'Gras', + Italic: 'Italique', + Strike: 'Barré', + Code: 'Code en ligne', + Line: 'Ligne', + Blockquote: 'Citation', + 'Unordered list': 'Liste non-ordonnée', + 'Ordered list': 'Liste ordonnée', + Task: 'Tâche', + Indent: 'Retrait', + Outdent: 'Sortir', + 'Insert link': 'Insérer un lien', + 'Insert CodeBlock': 'Insérer un bloc de code', + 'Insert table': 'Insérer un tableau', + 'Insert image': 'Insérer une image', + Heading: 'En-tête', + 'Image URL': "URL de l'image", + 'Select image file': 'Sélectionnez un fichier image', + Description: 'Description', + OK: 'OK', + More: 'de plus', + Cancel: 'Annuler', + File: 'Fichier', + URL: 'URL', + 'Link text': 'Texte du lien', + 'Add row': 'Ajouter une ligne', + 'Add col': 'Ajouter une colonne', + 'Remove row': 'Supprimer une ligne', + 'Remove col': 'Supprimer une colonne', + 'Align left': 'Aligner à gauche', + 'Align center': 'Aligner au centre', + 'Align right': 'Aligner à droite', + 'Remove table': 'Supprimer le tableau', + 'Would you like to paste as table?': 'Voulez-vous coller ce contenu en tant que tableau ?', + 'Text color': 'Couleur du texte', + 'Auto scroll enabled': 'Défilement automatique activé', + 'Auto scroll disabled': 'Défilement automatique désactivé', + 'Choose language': 'Choix de la langue' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/gl-es.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/gl-es.js new file mode 100644 index 0000000000..ad0bdc156f --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/gl-es.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 7); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 7: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Spanish + * @author Aida Vidal + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['gl', 'gl-ES'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Escribir', + Preview: 'Vista previa', + Headings: 'Encabezados', + Paragraph: 'Parágrafo', + Bold: 'Negriña', + Italic: 'Cursiva', + Strike: 'Riscado', + Code: 'Código', + Line: 'Liña', + Blockquote: 'Cita', + 'Unordered list': 'Lista desordenada', + 'Ordered list': 'Lista ordenada', + Task: 'Tarefa', + Indent: 'Sangría', + Outdent: 'Anular sangría', + 'Insert link': 'Inserir enlace', + 'Insert CodeBlock': 'Inserir bloque de código', + 'Insert table': 'Inserir táboa', + 'Insert image': 'Inserir imaxe', + Heading: 'Encabezado', + 'Image URL': 'URL da imaxe', + 'Select image file': 'Seleccionar arquivo da imaxe', + Description: 'Descrición', + OK: 'Aceptar', + More: 'Máis', + Cancel: 'Cancelar', + File: 'Arquivo', + URL: 'URL', + 'Link text': 'Texto do enlace', + 'Add row': 'Agregar fila', + 'Add col': 'Agregar columna', + 'Remove row': 'Eliminar fila', + 'Remove col': 'Eliminar columna', + 'Align left': 'Aliñar á esquerda', + 'Align center': 'Centrar', + 'Align right': 'Aliñar á dereita', + 'Remove table': 'Eliminar táboa', + 'Would you like to paste as table?': 'Desexa pegar como táboa?', + 'Text color': 'Cor do texto', + 'Auto scroll enabled': 'Desprazamento automático habilitado', + 'Auto scroll disabled': 'Desprazamento automático deshabilitado', + 'Choose language': 'Elixir idioma' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/hr-hr.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/hr-hr.js new file mode 100644 index 0000000000..d934dd03cf --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/hr-hr.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 8); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 8: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Croatian + * @author Hrvoje A. + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['hr', 'hr-HR'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Piši', + Preview: 'Pregled', + Headings: 'Naslovi', + Paragraph: 'Paragraf', + Bold: 'podebljano', + Italic: 'kurziv', + Strike: 'prcrtano', + Code: 'Uklopljeni kôd', + Line: 'Linija', + Blockquote: 'Blok citat', + 'Unordered list': 'Neporedana lista', + 'Ordered list': 'Poredana lista', + Task: 'Task', + Indent: 'Povećaj uvlaku', + Outdent: 'Smanji uvlaku', + 'Insert link': 'Umetni link', + 'Insert CodeBlock': 'Umetni blok kôda', + 'Insert table': 'Umetni tablicu', + 'Insert image': 'Umetni sliku', + Heading: 'Naslov', + 'Image URL': 'URL slike', + 'Select image file': 'Odaberi slikovnu datoteku', + Description: 'Opis', + OK: 'OK', + More: 'Više', + Cancel: 'Odustani', + File: 'Datoteka', + URL: 'URL', + 'Link text': 'Tekst linka', + 'Add row': 'Dodaj redak', + 'Add col': 'Dodaj stupac', + 'Remove row': 'Ukloni redak', + 'Remove col': 'Remove stupac', + 'Align left': 'Poravnaj lijevo', + 'Align center': 'Poravnaj centrirano', + 'Align right': 'Poravnaj desno', + 'Remove table': 'Ukloni tablicu', + 'Would you like to paste as table?': 'Zalite li zalijepiti kao tablicu?', + 'Text color': 'Boja teksta', + 'Auto scroll enabled': 'Omogući auto klizanje', + 'Auto scroll disabled': 'Onemogući auto klizanje', + 'Choose language': 'Odabir jezika' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/it-it.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/it-it.js new file mode 100644 index 0000000000..a73129c92f --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/it-it.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 9); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 9: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Italian + * @author Massimo Redaelli + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['it', 'it-IT'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Scrivere', + Preview: 'Anteprima', + Headings: 'Intestazioni', + Paragraph: 'Paragrafo', + Bold: 'Grassetto', + Italic: 'Corsivo', + Strike: 'Barrato', + Code: 'Codice', + Line: 'Linea', + Blockquote: 'Blocco citazione', + 'Unordered list': 'Lista puntata', + 'Ordered list': 'Lista numerata', + Task: 'Attività', + Indent: 'Aggiungi indentazione', + Outdent: 'Rimuovi indentazione', + 'Insert link': 'Inserisci link', + 'Insert CodeBlock': 'Inserisci blocco di codice', + 'Insert table': 'Inserisci tabella', + 'Insert image': 'Inserisci immagine', + Heading: 'Intestazione', + 'Image URL': 'URL immagine', + 'Select image file': 'Seleziona file immagine', + Description: 'Descrizione', + OK: 'OK', + More: 'Più', + Cancel: 'Cancella', + File: 'File', + URL: 'URL', + 'Link text': 'Testo del collegamento', + 'Add row': 'Aggiungi riga', + 'Add col': 'Aggiungi colonna', + 'Remove row': 'Rimuovi riga', + 'Remove col': 'Rimuovi colonna', + 'Align left': 'Allinea a sinistra', + 'Align center': 'Allinea al centro', + 'Align right': 'Allinea a destra', + 'Remove table': 'Rimuovi tabella', + 'Would you like to paste as table?': 'Desideri incollare sotto forma di tabella?', + 'Text color': 'Colore del testo', + 'Auto scroll enabled': 'Scrolling automatico abilitato', + 'Auto scroll disabled': 'Scrolling automatico disabilitato', + 'Choose language': 'Scegli la lingua' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ja-jp.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ja-jp.js new file mode 100644 index 0000000000..5408e65ad8 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ja-jp.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 10); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 10: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Japanese + * @author NHN FE Development Lab + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['ja', 'ja-JP'], { + Markdown: 'マークダウン', + WYSIWYG: 'WYSIWYG', + Write: '編集する', + Preview: 'プレビュー', + Headings: '見出し', + Paragraph: '本文', + Bold: '太字', + Italic: 'イタリック', + Strike: 'ストライク', + Code: 'インラインコード', + Line: 'ライン', + Blockquote: '引用', + 'Unordered list': '番号なしリスト', + 'Ordered list': '順序付きリスト', + Task: 'タスク', + Indent: 'インデント', + Outdent: 'アウトデント', + 'Insert link': 'リンク挿入', + 'Insert CodeBlock': 'コードブロック挿入', + 'Insert table': 'テーブル挿入', + 'Insert image': '画像挿入', + Heading: '見出し', + 'Image URL': 'イメージURL', + 'Select image file': '画像ファイル選択', + Description: 'ディスクリプション ', + OK: 'はい', + More: 'もっと', + Cancel: 'キャンセル', + File: 'ファイル', + URL: 'URL', + 'Link text': 'リンクテキスト', + 'Add row': '行追加', + 'Add col': '列追加', + 'Remove row': '行削除', + 'Remove col': '列削除', + 'Align left': '左揃え', + 'Align center': '中央揃え', + 'Align right': '右揃え', + 'Remove table': 'テーブル削除', + 'Would you like to paste as table?': 'テーブルを貼り付けますか?', + 'Text color': '文字色相', + 'Auto scroll enabled': '自動スクロールが有効', + 'Auto scroll disabled': '自動スクロールを無効に', + 'Choose language': '言語選択' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ko-kr.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ko-kr.js new file mode 100644 index 0000000000..cb43e2ec04 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ko-kr.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 11); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 11: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Korean + * @author NHN FE Development Lab + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['ko', 'ko-KR'], { + Markdown: '마크다운', + WYSIWYG: '위지윅', + Write: '편집하기', + Preview: '미리보기', + Headings: '제목크기', + Paragraph: '본문', + Bold: '굵게', + Italic: '기울임꼴', + Strike: '취소선', + Code: '인라인 코드', + Line: '문단나눔', + Blockquote: '인용구', + 'Unordered list': '글머리 기호', + 'Ordered list': '번호 매기기', + Task: '체크박스', + Indent: '들여쓰기', + Outdent: '내어쓰기', + 'Insert link': '링크 삽입', + 'Insert CodeBlock': '코드블럭 삽입', + 'Insert table': '표 삽입', + 'Insert image': '이미지 삽입', + Heading: '제목', + 'Image URL': '이미지 주소', + 'Select image file': '이미지 파일을 선택하세요.', + Description: '설명', + OK: '확인', + More: '더 보기', + Cancel: '취소', + File: '파일', + URL: '주소', + 'Link text': '링크 텍스트', + 'Add row': '행 추가', + 'Add col': '열 추가', + 'Remove row': '행 삭제', + 'Remove col': '열 삭제', + 'Align left': '왼쪽 정렬', + 'Align center': '가운데 정렬', + 'Align right': '오른쪽 정렬', + 'Remove table': '표 삭제', + 'Would you like to paste as table?': '표형태로 붙여 넣겠습니까?', + 'Text color': '글자 색상', + 'Auto scroll enabled': '자동 스크롤 켜짐', + 'Auto scroll disabled': '자동 스크롤 꺼짐', + 'Choose language': '언어 선택' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/nb-no.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/nb-no.js new file mode 100644 index 0000000000..3be393c544 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/nb-no.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 12); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 12: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Norwegian + * @author Anton Reytarovskiy + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['nb', 'nb-NO'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Skriv', + Preview: 'Forhåndsvis', + Headings: 'Overskrifter', + Paragraph: 'Avsnitt', + Bold: 'Fet skrift', + Italic: 'Kursiv', + Strike: 'Gjennomstrek', + Code: 'Kode', + Line: 'Linje', + Blockquote: 'Blokksitat', + 'Unordered list': 'Usortert liste', + 'Ordered list': 'Sortert liste', + Task: 'Task', + Indent: 'Indent', + Outdent: 'Outdent', + 'Insert link': 'Sett inn lenke', + 'Insert CodeBlock': 'Sett inn CodeStreng', + 'Insert table': 'Sett inn diagram', + 'Insert image': 'Sett inn bilde', + Heading: 'Overskrift', + 'Image URL': 'BildeURL', + 'Select image file': 'Velg bildefil', + Description: 'Beskrivelse', + OK: 'OK', + More: 'Mer', + Cancel: 'Angre', + File: 'Fil', + URL: 'URL', + 'Link text': 'Lenketekst', + 'Add row': 'Legg til rad', + 'Add col': 'Legg til kolonne', + 'Remove row': 'Fjern rad', + 'Remove col': 'Fjern kolonne', + 'Align left': 'Venstreorienter', + 'Align center': 'Senterorienter', + 'Align right': 'Høyreorienter', + 'Remove table': 'Fjern diagram', + 'Would you like to paste as table?': 'Ønsker du å lime inn som en tabell?', + 'Text color': 'Tekstfarge', + 'Auto scroll enabled': 'Auto-scroll aktivert', + 'Auto scroll disabled': 'Auto-scroll deaktivert', + 'Choose language': 'Velg språk' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/nl-nl.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/nl-nl.js new file mode 100644 index 0000000000..b55d49c628 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/nl-nl.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 13); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 13: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Dutch + * @author NHN FE Development Lab + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['nl', 'nl-NL'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Opslaan', + Preview: 'Voorbeeld', + Headings: 'Koppen', + Paragraph: 'Alinea', + Bold: 'Vet', + Italic: 'Cursief', + Strike: 'Doorhalen', + Code: 'Inline code', + Line: 'Regel', + Blockquote: 'Citaatblok', + 'Unordered list': 'Opsomming', + 'Ordered list': 'Genummerde opsomming', + Task: 'Taak', + Indent: 'Niveau verhogen', + Outdent: 'Niveau verlagen', + 'Insert link': 'Link invoegen', + 'Insert CodeBlock': 'Codeblok toevoegen', + 'Insert table': 'Tabel invoegen', + 'Insert image': 'Afbeelding invoegen', + Heading: 'Kop', + 'Image URL': 'Afbeelding URL', + 'Select image file': 'Selecteer een afbeelding', + Description: 'Omschrijving', + OK: 'OK', + More: 'Meer', + Cancel: 'Annuleren', + File: 'Bestand', + URL: 'URL', + 'Link text': 'Link tekst', + 'Add row': 'Rij toevoegen', + 'Add col': 'Kolom toevoegen', + 'Remove row': 'Rij verwijderen', + 'Remove col': 'Kolom verwijderen', + 'Align left': 'Links uitlijnen', + 'Align center': 'Centreren', + 'Align right': 'Rechts uitlijnen', + 'Remove table': 'Verwijder tabel', + 'Would you like to paste as table?': 'Wil je dit als tabel plakken?', + 'Text color': 'Tekstkleur', + 'Auto scroll enabled': 'Autoscroll ingeschakeld', + 'Auto scroll disabled': 'Autoscroll uitgeschakeld', + 'Choose language': 'Kies een taal' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/pl-pl.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/pl-pl.js new file mode 100644 index 0000000000..acb8b23ad1 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/pl-pl.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 14); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 14: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Polish + * @author Marcin Mikołajczak + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['pl', 'pl-PL'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Napisz', + Preview: 'Podgląd', + Headings: 'Nagłówki', + Paragraph: 'Akapit', + Bold: 'Pogrubienie', + Italic: 'Kursywa', + Strike: 'Przekreślenie', + Code: 'Fragment kodu', + Line: 'Linia', + Blockquote: 'Cytat', + 'Unordered list': 'Lista nieuporządkowana', + 'Ordered list': 'Lista uporządkowana', + Task: 'Zadanie', + Indent: 'Utwórz wcięcie', + Outdent: 'Usuń wcięcie', + 'Insert link': 'Umieść odnośnik', + 'Insert CodeBlock': 'Umieść blok kodu', + 'Insert table': 'Umieść tabelę', + 'Insert image': 'Umieść obraz', + Heading: 'Nagłówek', + 'Image URL': 'Adres URL obrazu', + 'Select image file': 'Wybierz plik obrazu', + Description: 'Opis', + OK: 'OK', + More: 'Więcej', + Cancel: 'Anuluj', + File: 'Plik', + URL: 'URL', + 'Link text': 'Tekst odnośnika', + 'Add row': 'Dodaj rząd', + 'Add col': 'Dodaj kolumnę', + 'Remove row': 'Usuń rząd', + 'Remove col': 'Usuń kolumnę', + 'Align left': 'Wyrównaj do lewej', + 'Align center': 'Wyśrodkuj', + 'Align right': 'Wyrównaj do prawej', + 'Remove table': 'Usuń tabelę', + 'Would you like to paste as table?': 'Czy chcesz wkleić tekst jako tabelę?', + 'Text color': 'Kolor tekstu', + 'Auto scroll enabled': 'Włączono automatyczne przewijanie', + 'Auto scroll disabled': 'Wyłączono automatyczne przewijanie', + 'Choose language': 'Wybierz język' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/pt-br.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/pt-br.js new file mode 100644 index 0000000000..c5eb97233b --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/pt-br.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 15); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 15: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Português + * @author Nícolas Huber + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['pt', 'pt-BR'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Escrever', + Preview: 'Pré-visualizar', + Headings: 'Cabeçalhos', + Paragraph: 'Parágrafo', + Bold: 'Negrito', + Italic: 'Itálico', + Strike: 'Traçado', + Code: 'Código', + Line: 'Linha', + Blockquote: 'Bloco de citação', + 'Unordered list': 'Lista não ordenada', + 'Ordered list': 'Lista ordenada', + Task: 'Tarefa', + Indent: 'Recuo à esquerda', + Outdent: 'Recuo à direita', + 'Insert link': 'Inserir link', + 'Insert CodeBlock': 'Inserir bloco de código', + 'Insert table': 'Inserir tabela', + 'Insert image': 'Inserir imagem', + Heading: 'Título', + 'Image URL': 'URL da imagem', + 'Select image file': 'Selecione um arquivo de imagem', + Description: 'Descrição', + OK: 'OK', + More: 'Mais', + Cancel: 'Cancelar', + File: 'Arquivo', + URL: 'URL', + 'Link text': 'Link de texto', + 'Add row': 'Adicionar linha', + 'Add col': 'Adicionar coluna', + 'Remove row': 'Remover linha', + 'Remove col': 'Remover coluna', + 'Align left': 'Alinhar à esquerda', + 'Align center': 'Alinhar ao centro', + 'Align right': 'Alinhar à direita', + 'Remove table': 'Remover tabela', + 'Would you like to paste as table?': 'Você gostaria de colar como mesa?', + 'Text color': 'Cor do texto', + 'Auto scroll enabled': 'Rolagem automática habilitada', + 'Auto scroll disabled': 'Rolagem automática desabilitada', + 'Choose language': 'Escolher linguagem' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ru-ru.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ru-ru.js new file mode 100644 index 0000000000..dd2a5462f5 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/ru-ru.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 16); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 16: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Russian + * @author Stepan Samko + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['ru', 'ru-RU'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Написать', + Preview: 'Предварительный просмотр', + Headings: 'Заголовки', + Paragraph: 'Абзац', + Bold: 'Жирный', + Italic: 'Курсив', + Strike: 'Зачеркнутый', + Code: 'Встроенный код', + Line: 'Строка', + Blockquote: 'Блок цитирования', + 'Unordered list': 'Неупорядоченный список', + 'Ordered list': 'Упорядоченный список', + Task: 'Задача', + Indent: 'отступ', + Outdent: 'Выступ', + 'Insert link': 'Вставить ссылку', + 'Insert CodeBlock': 'Вставить код', + 'Insert table': 'Вставить таблицу', + 'Insert image': 'Вставить изображение', + Heading: 'Заголовок', + 'Image URL': 'URL изображения', + 'Select image file': 'Выбрать файл изображения', + Description: 'Описание', + OK: 'Хорошо', + More: 'еще', + Cancel: 'Отмена', + File: 'Файл', + URL: 'URL', + 'Link text': 'Текст ссылки', + 'Add row': 'Добавить ряд', + 'Add col': 'Добавить столбец', + 'Remove row': 'Удалить ряд', + 'Remove col': 'Удалить столбец', + 'Align left': 'Выровнять по левому краю', + 'Align center': 'Выровнять по центру', + 'Align right': 'Выровнять по правому краю', + 'Remove table': 'Удалить таблицу', + 'Would you like to paste as table?': 'Вы хотите вставить в виде таблицы?', + 'Text color': 'Цвет текста', + 'Auto scroll enabled': 'Автоматическая прокрутка включена', + 'Auto scroll disabled': 'Автоматическая прокрутка отключена', + 'Choose language': 'Выбрать язык' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/sv-se.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/sv-se.js new file mode 100644 index 0000000000..8a69357086 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/sv-se.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 17); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 17: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Swedish + * @author Magnus Aspling + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['sv', 'sv-SE'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Skriv', + Preview: 'Förhandsgranska', + Headings: 'Överskrifter', + Paragraph: 'Paragraf', + Bold: 'Fet', + Italic: 'Kursiv', + Strike: 'Genomstruken', + Code: 'Kodrad', + Line: 'Linje', + Blockquote: 'Citatblock', + 'Unordered list': 'Punktlista', + 'Ordered list': 'Numrerad lista', + Task: 'Att göra', + Indent: 'Öka indrag', + Outdent: 'Minska indrag', + 'Insert link': 'Infoga länk', + 'Insert CodeBlock': 'Infoga kodblock', + 'Insert table': 'Infoga tabell', + 'Insert image': 'Infoga bild', + Heading: 'Överskrift', + 'Image URL': 'Bildadress', + 'Select image file': 'Välj en bildfil', + Description: 'Beskrivning', + OK: 'OK', + More: 'Mer', + Cancel: 'Avbryt', + File: 'Fil', + URL: 'Adress', + 'Link text': 'Länktext', + 'Add row': 'Infoga rad', + 'Add col': 'Infoga kolumn', + 'Remove row': 'Radera rad', + 'Remove col': 'Radera kolumn', + 'Align left': 'Vänsterjustera', + 'Align center': 'Centrera', + 'Align right': 'Högerjustera', + 'Remove table': 'Radera tabell', + 'Would you like to paste as table?': 'Vill du klistra in som en tabell?', + 'Text color': 'Textfärg', + 'Auto scroll enabled': 'Automatisk scroll aktiverad', + 'Auto scroll disabled': 'Automatisk scroll inaktiverad', + 'Choose language': 'Välj språk' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/tr-tr.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/tr-tr.js new file mode 100644 index 0000000000..5a6e877f6f --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/tr-tr.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 18); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 18: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Turkish + * @author Mesut Gölcük + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['tr', 'tr-TR'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Düzenle', + Preview: 'Ön izleme', + Headings: 'Başlıklar', + Paragraph: 'Paragraf', + Bold: 'Kalın', + Italic: 'İtalik', + Strike: 'Altı çizgili', + Code: 'Satır içi kod', + Line: 'Çizgi', + Blockquote: 'Alıntı', + 'Unordered list': 'Sıralanmamış liste', + 'Ordered list': 'Sıralı liste', + Task: 'Görev kutusu', + Indent: 'Girintiyi arttır', + Outdent: 'Girintiyi azalt', + 'Insert link': 'Bağlantı ekle', + 'Insert CodeBlock': 'Kod bloku ekle', + 'Insert table': 'Tablo ekle', + 'Insert image': 'İmaj ekle', + Heading: 'Başlık', + 'Image URL': 'İmaj URL', + 'Select image file': 'İmaj dosyası seç', + Description: 'Açıklama', + OK: 'Onay', + More: 'Daha Fazla', + Cancel: 'İptal', + File: 'Dosya', + URL: 'URL', + 'Link text': 'Bağlantı yazısı', + 'Add row': 'Satır ekle', + 'Add col': 'Sütun ekle', + 'Remove row': 'Satır sil', + 'Remove col': 'Sütun sil', + 'Align left': 'Sola hizala', + 'Align center': 'Merkeze hizala', + 'Align right': 'Sağa hizala', + 'Remove table': 'Tabloyu kaldır', + 'Would you like to paste as table?': 'Tablo olarak yapıştırmak ister misiniz?', + 'Text color': 'Metin rengi', + 'Auto scroll enabled': 'Otomatik kaydırma açık', + 'Auto scroll disabled': 'Otomatik kaydırma kapalı', + 'Choose language': 'Dil seçiniz' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/uk-ua.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/uk-ua.js new file mode 100644 index 0000000000..e42497035e --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/uk-ua.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 19); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 19: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Ukrainian + * @author Nikolya + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage(['uk', 'uk-UA'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Написати', + Preview: 'Попередній перегляд', + Headings: 'Заголовки', + Paragraph: 'Абзац', + Bold: 'Жирний', + Italic: 'Курсив', + Strike: 'Закреслений', + Code: 'Вбудований код', + Line: 'Лінія', + Blockquote: 'Блок цитування', + 'Unordered list': 'Невпорядкований список', + 'Ordered list': 'Упорядкований список', + Task: 'Завдання', + Indent: 'відступ', + Outdent: 'застарілий', + 'Insert link': 'Вставити посилання', + 'Insert CodeBlock': 'Вставити код', + 'Insert table': 'Вставити таблицю', + 'Insert image': 'Вставити зображення', + Heading: 'Заголовок', + 'Image URL': 'URL зображення', + 'Select image file': 'Вибрати файл зображення', + Description: 'Опис', + OK: 'OK', + More: 'ще', + Cancel: 'Скасувати', + File: 'Файл', + URL: 'URL', + 'Link text': 'Текст посилання', + 'Add row': 'Додати ряд', + 'Add col': 'Додати стовпчик', + 'Remove row': 'Видалити ряд', + 'Remove col': 'Видалити стовпчик', + 'Align left': 'Вирівняти по лівому краю', + 'Align center': 'Вирівняти по центру', + 'Align right': 'Вирівняти по правому краю', + 'Remove table': 'Видалити таблицю', + 'Would you like to paste as table?': 'Ви хочете вставити у вигляді таблиці?', + 'Text color': 'Колір тексту', + 'Auto scroll enabled': 'Автоматична прокрутка включена', + 'Auto scroll disabled': 'Автоматична прокрутка відключена', + 'Choose language': 'Вибрати мову' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/zh-cn.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/zh-cn.js new file mode 100644 index 0000000000..5dd3332e70 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/zh-cn.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 20); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 20: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Chinese + * @author NHN FE Development Lab + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage('zh-CN', { + Markdown: 'Markdown', + WYSIWYG: '所见即所得', + Write: '编辑', + Preview: '预览', + Headings: '标题', + Paragraph: '文本', + Bold: '加粗', + Italic: '斜体字', + Strike: '删除线', + Code: '内嵌代码', + Line: '水平线', + Blockquote: '引用块', + 'Unordered list': '无序列表', + 'Ordered list': '有序列表', + Task: '任务', + Indent: '缩进', + Outdent: '减少缩进', + 'Insert link': '插入链接', + 'Insert CodeBlock': '插入代码块', + 'Insert table': '插入表格', + 'Insert image': '插入图片', + Heading: '标题', + 'Image URL': '图片网址', + 'Select image file': '选择图片文件', + Description: '说明', + OK: '确认', + More: '更多', + Cancel: '取消', + File: '文件', + URL: 'URL', + 'Link text': '链接文本', + 'Add row': '添加行', + 'Add col': '添加列', + 'Remove row': '删除行', + 'Remove col': '删除列', + 'Align left': '左对齐', + 'Align center': '居中对齐', + 'Align right': '右对齐', + 'Remove table': '删除表格', + 'Would you like to paste as table?': '需要粘贴为表格吗?', + 'Text color': '文字颜色', + 'Auto scroll enabled': '自动滚动已启用', + 'Auto scroll disabled': '自动滚动已禁用', + 'Choose language': '选择语言' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/zh-tw.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/zh-tw.js new file mode 100644 index 0000000000..684b689d8a --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/i18n/zh-tw.js @@ -0,0 +1,174 @@ +/*! + * TOAST UI Editor : i18n + * @version 2.5.1 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("@toast-ui/editor")); + else if(typeof define === 'function' && define.amd) + define(["@toast-ui/editor"], factory); + else { + var a = typeof exports === 'object' ? factory(require("@toast-ui/editor")) : factory(root["toastui"]["Editor"]); + for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; + } +})(window, function(__WEBPACK_EXTERNAL_MODULE__0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 21); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ 0: +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__0__; + +/***/ }), + +/***/ 21: +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0); +/* harmony import */ var _editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_editor__WEBPACK_IMPORTED_MODULE_0__); +/** + * @fileoverview I18N for Traditional Chinese + * @author Tzu-Ray Su + */ + +_editor__WEBPACK_IMPORTED_MODULE_0___default.a.setLanguage('zh-TW', { + Markdown: 'Markdown', + WYSIWYG: '所見即所得', + Write: '編輯', + Preview: '預覽', + Headings: '標題', + Paragraph: '內文', + Bold: '粗體', + Italic: '斜體', + Strike: '刪除線', + Code: '內嵌程式碼', + Line: '分隔線', + Blockquote: '引言', + 'Unordered list': '項目符號清單', + 'Ordered list': '編號清單', + Task: '核取方塊清單', + Indent: '增加縮排', + Outdent: '減少縮排', + 'Insert link': '插入超連結', + 'Insert CodeBlock': '插入程式碼區塊', + 'Insert table': '插入表格', + 'Insert image': '插入圖片', + Heading: '標題', + 'Image URL': '圖片網址', + 'Select image file': '選擇圖片檔案', + Description: '描述', + OK: '確認', + More: '更多', + Cancel: '取消', + File: '檔案', + URL: 'URL', + 'Link text': '超連結文字', + 'Add row': '增加行', + 'Add col': '增加列', + 'Remove row': '刪除行', + 'Remove col': '刪除列', + 'Align left': '靠左對齊', + 'Align center': '置中', + 'Align right': '靠右對齊', + 'Remove table': '刪除表格', + 'Would you like to paste as table?': '您要以表格貼上嗎?', + 'Text color': '文字顏色', + 'Auto scroll enabled': '已啟用自動滾動', + 'Auto scroll disabled': '已停用自動滾動', + 'Choose language': '選擇語言' +}); + +/***/ }) + +/******/ }); +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-old.css b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-old.css new file mode 100644 index 0000000000..6499cff350 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-old.css @@ -0,0 +1,1649 @@ +/*! + * @toast-ui/editor + * @version 2.5.1 | Tue Nov 24 2020 + * @author NHN FE Development Lab + * @license MIT + */ +/* height */ +.auto-height, +.auto-height .tui-editor-defaultUI { + height: auto; +} + +.auto-height .tui-editor { + position: relative; +} + +:not(.auto-height) > .tui-editor-defaultUI, +:not(.auto-height) > .tui-editor-defaultUI > .te-editor-section { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; +} + +:not(.auto-height) > .tui-editor-defaultUI > .te-editor-section { + -ms-flex: 1; + flex: 1; +} + +/* tui editor */ +.tui-editor:after, +.tui-editor-defaultUI-toolbar:after { + content: ''; + display: block; + height: 0; + clear: both; +} + +.tui-editor { + position: absolute; + line-height: 1; + color: #181818; + width: 100%; + height: inherit; +} + +.te-editor-section { + min-height: 0px; + position: relative; + height: inherit; +} + +.te-md-container { + display: none; + overflow: hidden; + height: 100%; +} + +.te-md-container .te-editor { + line-height: 1.5; +} + +.te-md-container .te-editor, +.te-md-container .te-preview { + box-sizing: border-box; + padding: 0; + height: inherit; +} + +.te-md-container .CodeMirror { + font-size: 13px; + height: inherit; +} + +.te-md-container .te-preview { + overflow: auto; + padding: 0 25px; + height: 100%; +} + +.te-md-container .te-preview > p:first-child { + margin-top: 0 !important; +} + +.te-md-container .te-preview .tui-editor-contents { + padding-top: 8px; +} + +.tui-editor .te-preview-style-tab > .te-editor, +.tui-editor .te-preview-style-tab > .te-preview { + float: left; + width: 100%; + display: none; +} + +.tui-editor .te-preview-style-tab > .te-tab-active { + display: block; +} + +.tui-editor .te-preview-style-vertical > .te-tab-section { + display: none; +} + +.tui-editor .te-preview-style-tab > .te-tab-section { + display: block; +} + +.tui-editor .te-preview-style-vertical .te-editor { + float: left; + width: 50%; +} + +.tui-editor .te-preview-style-vertical .te-preview { + float: left; + width: 50%; +} + +.tui-editor .te-md-splitter { + display: none; + position: absolute; + left: 50%; + top: 0; + height: 100%; + width: 1px; + border-left: 1px solid #e5e5e5; +} + +.tui-editor .te-preview-style-vertical .te-md-splitter { + display: block; +} + +.te-ww-container { + display: none; + overflow: hidden; + z-index: 10; + height: inherit; + background-color: #fff; +} + +.te-ww-container > .te-editor { + overflow: auto; + height: inherit; +} + +.te-ww-container .tui-editor-contents:focus { + outline: none; +} + +.te-ww-container .tui-editor-contents { + padding: 0 25px; +} + +.te-ww-container .tui-editor-contents:first-child { + box-sizing: border-box; + margin: 0px; + padding: 16px 25px 0px 25px; + height: inherit; +} + +.te-ww-container .tui-editor-contents:last-child { + margin-bottom: 16px; +} + +.te-md-mode .te-md-container { + display: block; + z-index: 100; +} + +.te-ww-mode .te-ww-container { + display: block; + z-index: 100; +} + +.tui-editor.te-hide, +.tui-editor-defaultUI.te-hide { + display: none; +} + +.tui-editor-defaultUI .CodeMirror-lines { + padding-top: 18px; + padding-bottom: 18px; +} + +.tui-editor-defaultUI pre.CodeMirror-line { + padding-left: 25px; + padding-right: 25px; +} + +.tui-editor-defaultUI .CodeMirror pre.CodeMirror-placeholder { + margin: 0; + padding-left: 25px; + color: grey; +} + +.tui-editor-defaultUI .CodeMirror-scroll { + cursor: text; +} + +/* Essential element style */ +.tui-editor-contents td.te-cell-selected { + background-color: #d8dfec; +} +.tui-editor-contents td.te-cell-selected::selection { + background-color: #d8dfec; +} +.tui-editor-contents th.te-cell-selected { + background-color: #908f8f; +} +.tui-editor-contents th.te-cell-selected::selection { + background-color: #908f8f; +} + +/* default UI Styles */ +.tui-editor-defaultUI { + position: relative; + border: 1px solid #e5e5e5; + height: 100%; + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +.tui-editor-defaultUI button { + color: #fff; + padding: 0px 14px 0px 15px; + height: 28px; + font-size: 12px; + border: none; + cursor: pointer; + outline: none; +} +.tui-editor-defaultUI button.te-ok-button { + background-color: #4b96e6; +} +.tui-editor-defaultUI button.te-close-button { + background-color: #777; +} + +.tui-editor-defaultUI-toolbar { + padding: 0 25px; + height: 31px; + background-color: #fff; + border: 0; + overflow: hidden; +} + +.tui-toolbar-divider { + float: left; + display: inline-block; + width: 1px; + height: 14px; + background-color: #ddd; + margin: 9px 6px; +} + +.tui-toolbar-button-group { + height: 28px; + border-right: 1px solid #d9d9d9; + float: left; +} + +.te-toolbar-section { + height: 32px; + box-sizing: border-box; + border-bottom: 1px solid #e5e5e5; +} + +.tui-editor-defaultUI-toolbar button { + float: left; + box-sizing: border-box; + outline: none; + cursor: pointer; + background-color: #fff; + width: 22px; + height: 22px; + padding: 3px; + border-radius: 0; + margin: 5px 3px; + border: 1px solid #fff; +} + +.tui-editor-defaultUI-toolbar button:hover, +.tui-editor-defaultUI-toolbar button:active, +.tui-editor-defaultUI-toolbar button.active { + border: 1px solid #aaa; + background-color: #fff; +} + +.tui-editor-defaultUI-toolbar button:first-child { + margin-left: 0; +} + +.tui-editor-defaultUI-toolbar button:last-child { + margin-right: 0; +} + +.tui-editor-defaultUI-toolbar button.tui-scrollsync { + width: auto; + color: #777777; + border: 0; +} + +.tui-editor-defaultUI button.tui-scrollsync:after { + content: 'Scroll off'; +} + +.tui-editor-defaultUI button.tui-scrollsync.active { + color: #125de6; + font-weight: bold; +} + +.tui-editor-defaultUI button.tui-scrollsync.active:after { + content: 'Scroll on'; +} + +.tui-editor-defaultUI .te-mode-switch-section { + background-color: #f9f9f9; + border-top: 1px solid #e5e5e5; + height: 20px; + font-size: 12px; +} + +.tui-editor-defaultUI .te-mode-switch { + float: right; + height: 100%; +} + +.tui-editor-defaultUI .te-switch-button { + width: 92px; + height: inherit; + background: #e5e5e5; + outline: 0; + color: #a0aabf; + cursor: pointer; + border: 0; + border-left: 1px solid #ddd; + border-right: 1px solid #ddd; +} + +.tui-editor-defaultUI .te-switch-button.active { + background-color: #fff; + color: #000; +} + +.tui-editor-defaultUI .te-markdown-tab-section { + float: left; + height: 31px; + background: #fff; +} + +.te-markdown-tab-section .te-tab { + margin: 0 -7px 0 24px; + background: #fff; +} + +.tui-editor-defaultUI .te-tab button { + box-sizing: border-box; + line-height: 100%; + position: relative; + cursor: pointer; + z-index: 1; + font-size: 13px; + background-color: #f9f9f9; + border: solid 1px #e5e5e5; + border-top: 0; + padding: 0 9px; + color: #777; + border-radius: 0; + outline: 0; +} + +.te-markdown-tab-section .te-tab button:last-child { + margin-left: -1px; +} + +.te-markdown-tab-section .te-tab button.te-tab-active, +.te-markdown-tab-section .te-tab button:hover.te-tab-active { + background-color: #fff; + color: #333; + border-bottom: 1px solid #fff; + z-index: 2; +} + +.te-markdown-tab-section .te-tab button:hover { + background-color: #fff; + color: #333; +} + +.tui-popup-modal-background { + background-color: rgba(202, 202, 202, 0.6); + position: fixed; + margin: 0px; + left: 0px; + top: 0px; + width: 100%; + height: 100%; + z-index: 9999; +} + +.tui-popup-wrapper.fit-window, +.tui-popup-modal-background.fit-window .tui-popup-wrapper { + width: 100%; + height: 100%; +} + +.tui-popup-wrapper { + width: 500px; + margin-right: auto; + border: 1px solid #cacaca; + background: white; + z-index: 9999; +} + +.tui-popup-modal-background .tui-popup-wrapper { + position: absolute; + margin: auto; + top: 0px; + right: 0px; + bottom: 0px; + left: 0px; +} + +.tui-popup-header { + padding: 10px; + height: auto; + line-height: normal; + position: relative; + border-bottom: 1px solid #cacaca; +} + +.tui-popup-header .tui-popup-header-buttons { + float: right; +} + +.tui-popup-header .tui-popup-header-buttons button { + padding: 0px; + background-color: transparent; + background-size: cover; + float: left; +} + +.tui-popup-header .tui-popup-close-button { + margin: 3px; + width: 13px; + height: 13px; + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxMHB4IiBoZWlnaHQ9IjEwcHgiIHZpZXdCb3g9IjAgMCAxMCAxMCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT5GMjc2Qzc4MC0zM0JBLTQ3MTItQTM3OC04RkQwQUNDOTFDRTk8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImxuYi1mb2xkZXItZGVsIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGZpbGw9IiM3Nzc3NzciPiAgICAgICAgICAgIDxwYXRoIGQ9Ik01LDMuNTg1Nzg2NDQgTDEuNzA3MTA2NzgsMC4yOTI4OTMyMTkgTDAuMjkyODkzMjE5LDEuNzA3MTA2NzggTDMuNTg1Nzg2NDQsNSBMMC4yOTI4OTMyMTksOC4yOTI4OTMyMiBMMS43MDcxMDY3OCw5LjcwNzEwNjc4IEw1LDYuNDE0MjEzNTYgTDguMjkyODkzMjIsOS43MDcxMDY3OCBMOS43MDcxMDY3OCw4LjI5Mjg5MzIyIEw2LjQxNDIxMzU2LDUgTDkuNzA3MTA2NzgsMS43MDcxMDY3OCBMOC4yOTI4OTMyMiwwLjI5Mjg5MzIxOSBMNSwzLjU4NTc4NjQ0IFoiIGlkPSJDb21iaW5lZC1TaGFwZSI+PC9wYXRoPiAgICAgICAgPC9nPiAgICA8L2c+PC9zdmc+); +} + +.tui-popup-header .tui-popup-title { + font-size: 13px; + font-weight: bold; + color: #333; + vertical-align: bottom; +} + +.tui-popup-body { + padding: 15px; + font-size: 12px; +} + +.tui-editor-popup { + position: absolute; + top: 30px; + left: 50%; + margin-left: -250px; +} + +.tui-editor-popup.tui-popup-modal-background { + position: fixed; + top: 0px; + left: 0px; + margin: 0px; +} + +.tui-editor-popup .tui-popup-body label { + font-weight: bold; + color: #666; + display: block; + margin: 10px 0 5px; +} + +.tui-editor-popup .tui-popup-body .te-button-section { + margin-top: 15px; +} + +.tui-editor-popup .tui-popup-body input[type='text'], +.tui-editor-popup .tui-popup-body input[type='file'] { + padding: 4px 10px; + border: 1px solid #bfbfbf; + box-sizing: border-box; + width: 100%; +} + +.tui-editor-popup .tui-popup-body input[type='text'].disabled { + border-color: #e5e5e5; + background-color: #eee; + color: #e5e5e5; +} + +.tui-editor-popup .tui-popup-body input.wrong { + border-color: #ff0000; +} + +.te-popup-add-link .tui-popup-wrapper { + height: 219px; +} + +.te-popup-add-image .tui-popup-wrapper { + height: 243px; +} + +.te-popup-add-image .te-tab { + display: block; + background: none; + border-bottom: 1px solid #ebebeb; + margin-bottom: 8px; +} + +.te-popup-add-image .te-url-type { + display: none; +} + +.te-popup-add-image .te-file-type { + display: none; +} + +.te-popup-add-image div.te-tab-active, +.te-popup-add-image form.te-tab-active { + display: block; +} + +.te-popup-add-image .te-tab button { + border: 1px solid #ccc; + background: #eee; + min-width: 100px; + margin-left: -1px; + border-bottom: 0px; + border-radius: 3px 3px 0px 0px; +} + +.te-popup-add-image .te-tab button.te-tab-active { + background: #fff; +} + +.te-popup-add-table .te-table-selection { + position: relative; +} + +.te-popup-add-table .te-table-body { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAARCAYAAAAougcOAAAC7mlDQ1BJQ0MgUHJvZmlsZQAAeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFkifEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UXAeIuJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOklEQVQ4EWO8e/fuPwYGBkYgphlgAZmspKREMwtABjPR1HSo4aOWkBTKo8E1GlwkhQBJikdT1wgNLgAMSwQgckFvTgAAAABJRU5ErkJggg=='); +} + +.te-popup-add-table .te-table-header { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAARCAYAAAAougcOAAAC7mlDQ1BJQ0MgUHJvZmlsZQAAeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFkifEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UXAeIuJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOklEQVQ4EWO8e/fuPwYGBkYgphlgAZksLCxMMwtABjPR1HSo4aOWkBTKo8E1GlwkhQBJikdT1wgNLgDxKwPzTeWPdAAAAABJRU5ErkJggg=='); +} + +.te-popup-add-table .te-selection-area { + position: absolute; + top: 0; + left: 0; + background: #80d2ff; + opacity: 0.3; + z-index: 999; +} + +.te-popup-add-table .te-description { + margin: 10px 0 0 0; + text-align: center; +} + +.te-popup-table-utils { + width: 120px; +} + +.te-popup-table-utils .tui-popup-body { + padding: 0px; +} + +.te-popup-table-utils button { + width: 100%; + background-color: #fff; + border: none; + outline: 0; + padding: 0px 10px 0px 10px; + font-size: 12px; + line-height: 28px; + text-align: left; + color: #777; +} + +.te-popup-table-utils button:hover { + background-color: #f4f4f4; +} + +.te-popup-table-utils hr { + background-color: #cacaca; + border-style: none; + height: 1px; +} + +.te-popup-table-utils .te-context-menu-disabled { + color: #ccc; +} + +.te-popup-table-utils .te-context-menu-disabled:hover { + background-color: #fff; +} + +.te-heading-add { + width: auto; +} + +.te-heading-add .tui-popup-body { + padding: 0; +} + +.te-heading-add h1, +.te-heading-add h2, +.te-heading-add h3, +.te-heading-add h4, +.te-heading-add h5, +.te-heading-add h6, +.te-heading-add ul, +.te-heading-add p { + padding: 0; + margin: 0; +} + +.te-heading-add ul { + list-style: none; +} + +.te-heading-add ul li { + padding: 2px 10px; + cursor: pointer; +} + +.te-heading-add ul li:hover { + background-color: #eee; +} + +.te-heading-add h1 { + font-size: 24px; +} + +.te-heading-add h2 { + font-size: 22px; +} + +.te-heading-add h3 { + font-size: 20px; +} + +.te-heading-add h4 { + font-size: 18px; +} + +.te-heading-add h5 { + font-size: 16px; +} + +.te-heading-add h6 { + font-size: 14px; +} + +.te-dropdown-toolbar { + position: absolute; + width: auto; +} + +.te-dropdown-toolbar .tui-popup-body { + padding: 0px; +} + +.tui-popup-color { + padding: 0; +} + +.tui-popup-color .tui-colorpicker-container, +.tui-popup-color .tui-colorpicker-palette-container { + width: 144px; +} + +.tui-popup-color .tui-colorpicker-container ul { + width: 144px; + margin-bottom: 8px; +} + +.tui-popup-color .tui-colorpicker-container li { + padding: 0 1px 1px 0; +} + +.tui-popup-color .tui-colorpicker-container li .tui-colorpicker-palette-button { + border: 0; + width: 17px; + height: 17px; +} + +.tui-popup-color .tui-popup-body { + padding: 10px; +} + +.tui-popup-color .tui-colorpicker-container .tui-colorpicker-palette-toggle-slider { + display: none; +} + +.tui-popup-color .te-apply-button, +.tui-popup-color .tui-colorpicker-palette-hex { + float: right; +} + +.tui-popup-color .te-apply-button { + height: 21px; + width: 35px; + background: #fff; + border: 1px solid #efefef; + position: absolute; + bottom: 135px; + right: 10px; + color: black; +} + +.tui-popup-color .tui-colorpicker-container .tui-colorpicker-palette-hex { + border: 1px solid #e1e1e1; + padding: 3px 14px; + margin-left: -1px; +} + +.tui-popup-color .tui-colorpicker-container div.tui-colorpicker-clearfix { + display: inline-block; +} + +.tui-popup-color .tui-colorpicker-container .tui-colorpicker-palette-preview { + width: 19px; + height: 19px; +} + +.tui-popup-color .tui-colorpicker-slider-container .tui-colorpicker-slider-right { + width: 22px; +} + +.tui-popup-color .tui-colorpicker-slider-container .tui-colorpicker-huebar-handle { + display: none; +} + +.tui-tooltip { + position: absolute; + background-color: #222; + z-index: 999; + opacity: 0.8; + color: #fff; + padding: 2px 5px; + font-size: 10px; +} + +.tui-tooltip .arrow { + content: ''; + display: inline-block; + width: 10px; + height: 10px; + background-color: #222; + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); + position: absolute; + top: -3px; + left: 6px; + z-index: -1; +} + +.tui-toolbar-icons { + background: url(data:image/png;base64,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); + background-size: 218px 188px; + display: inline-block; +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), + only screen and (min--moz-device-pixel-ratio: 2), + only screen and (-o-min-device-pixel-ratio: 2/1), + only screen and (min-device-pixel-ratio: 2), + only screen and (min-resolution: 192dpi), + only screen and (min-resolution: 2dppx) { + .tui-toolbar-icons { + background: url(data:image/png;base64,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Xqz8qBcJkED0BGIbcoxe1QtDor4qT80zFpNh01flYWg2e1Fo2C6Me5NnSQLFToAeWpFfITFmxbrCUdCJMeMKxyK/iageCZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACQQgkA5QNlTRRYsWZbwEbNu2LTFdnPSAftc6pas06PesihdTmIurXdekOefi6qBfpJyD8rHrk+s4LM+gfHLpY8+P+r6Ngmc6nf7q1q1b6+26RnEcBc/S0tLmLVu2HI5Cn6Ay7Hxz3V9BywfVx17ezjfX/RW0vL29oMclQSuwPAmQAAnkS0A3ZrW1tR9Gh1ebr6w46unGrK6ubiz0GxdHO5QZD4HEDJo8aeBmmWk7jf2SnuspxFYnlkN50pg8efJLNuHdki67LZ2HJEACAQnYjVl/f/+PIeLxYjFqdmPW0dExC/rNpFELeKELWDwxgybn2NfXt1A/V9zg2/XjQsePHz8+StcBN/gZ/ZhxEiCB/Ai4GLMKSCvFXnCj5mTMYHDVNAiNWn6XPfFaZUm2iJt6YSZzfioN8e1Jtp+rLegzUi8Dfdv14yTiixcvbhw7duxdDQ0Nb/ppL2nvdsmSJZfMmzfvQH19fb9P/Qrq3SbNxw8Tvcxg9/6D8pVhRsMzE2OmthJslodJlRE2DMpXhhnFM9OMWVaFsrKyRB/+w573hVo/0YsEg7FQB42nou36caHj8CAtP6qamprEPTQwuq21tfX3GOa4vNA8nNoHo/G7d++eD/2qnPKZRgJuBFyMWQbGbHVTU9NDbvWSSvcwZvs3b958PCk92E7+BBIzaPJkDzVnaKrux0qi17XjgkbXrFkzDAroT43da9eu7SqQUmLMxKjVFah9z2Z7e3sr8TAyb+nSpTWeBZl5wRGQewKjDP/bfuLFYswwslAmhsuuH42ZncjgPE7MoHH+LPANMhw1HpUhyNWrV0u8qDZczxIYthnyoIJOIrH7qKggUBkLATFmuCf+E4k/xsPYCpVZTMZsx44dc86ePXvpypUrxyv9aMwUicEfJjaHxvmz/G4WYwjyOnQQizAf8LJdCpLPT0raMx2Og855OIiwJBlDkCOgx17I7rBk4gDpnu/32csHnfOw1w96HJSfXX7UPO3yg/Kz10+Kp2bMrsQ9m8LvvRG6pzCc2OowZ5b4MKN4ZmLMwCc7VI55sktg1ES/Ppc5s6IYZgx7f9rvh6iPw96fUeuT2JM1589CXToOQYbCx8pxE8CDzbUwYvNVO/i9l4hRKwZjJjrBmI2A8apU+kkoRq2YjZmuK+P+CCRi0Dh/5u9i5CqFDiKQN5ZLXtT55eXlRa1f1OdLeecJ4Msfv4ARq8U92qNSxaghrs9LO3pmGFavV3XiCuGpnsK87z4YNcs96rCacYBnhv5ralx6UW60BBIxaJw/C33RZKjxOnQaj4WWFIMALGnuxDXetX79+hMxiKfIQUIARuMJu1HTVHc1Zqhzr1YutuimTZtanYyaahD3saMxw709RZVhWNwEEplDw1Mb3z/L8z4Au8e83kuLew4nl9roIE7MnTvX9b20pOZwcunpll9ofm56qfRi56f0VCH0fQLzKrIg5HHs8tJ0doNn9En70nzxzJIyZkoPMWrQT16Ytny1qLKy8uCGDRssS/PFMyu0Mct1fxZ6ji3X/Zn0HFsiBg037UJ1Q0mITnC7flzoOG7agr9/5sDgTRizu4rVK8M17K+oqDhAr8zhyl3gSejkmtCRCYWsUYMx+wSM2TodSyGMmWof+p009MsaNcOYHVX5EhaDMdP1YdwfgdiHHDl/5u9C2EpxiNEGhIeDi4AYNWi83MmYyZkk7ZnZ6YlRQ9o+J2MmZQvtmdn15bE/ArF7aLgxFuqqwOvYrh8XOl5s32/MNcRYaF65hhgLrR/bLx4ChlErHoVsmhhGzZbKw8FMIHaDhg6a82cB7hAMMdYFKC7veVlWbeWqix+xzB/kvQX9ukvQMXTo92zeyjlUDMrHQYRnUlieQfl4KuOQGTVPexNx87W3F/Q4br5B9WH5eAnEPuTI+bN4LyClkwAJkAAJnCMQm4fm9uSGIch9yEuFfbINewHdntxaWlquMPSL1FMIqy/rkwAJkAAJeBOI3UPzbp65JEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJFC8BNJRq7Zo0aKMLnPbtm2ebQQtr8vOJ472rtXrQb9n9WN7PGh5e/24j+38crWX63rkqh80384vV/1c1yNXfXt+UD72+rmOw/IMyieXPvb8qHkq+dB7TDqdvgPHtZlMZrak4/gVBE04fgjtnpI0tfm4Ds2ov728vPwLjz/++CFVL98Q7ZWWlZXV9Pf3j8M+TOSUlJR0YT/Z29t7HPr16bJzXQfI6oF+7T09PYdQt1uvG1fc0Om/bfLf5nRNX5xytaXftdVJvaX5j579sL28n+MVK1aM6OzsnKeXrays3LVhw4azeprEd065xtLv2vPnN//Bsx+2l3c7LnHLYDoJkAAJOBFYvHjxDUh/CYbrO9ivQ3ys7BKXNMkzyiDqe5uCuku7u7ufX758+TTftRwKrlq1ahQM0AIYrmkwZsNRpFR2iUua5EkZh6quSahXDmNWjQKXw9BUuBaMMAMG9E67OKc0e5mkjvv6+mrsbTml2cvEeUyDFiddyiaBIUYAnfn7YXh+jtPyMjrTpMySJUv+Zx6nPw6G4+/yqJetAmM4+uzZs7PFALnJkDwpI2Xdynikl8KL9Dp3j6r+s8B5pBh4ew1Jkzx7etLH0EEeEMbZ25U0ybOnJ3VMg5YUabZDAoOcwK233joFHkITTiM7hOd1Oij3Mzytv+BVxiPvfR55rlmrV68uh4c3C51qzuG10tLSthEjRnS4CvPIgFFJwqAsgwrZdsDy97IbKkma5BV6G4frm7UfGMZ9U3ZRyEgbYOiSUrYsqYbYTjgC+LEOb2trW7d169Y6XRLG03P+ePXyccXr6+tLdu3aNX3Lli2v6204jffr+XHHi4WP23kWmo+bXk7pMBb3ozOXYTd9a0Rn9nUM4x1D/v9Ax3sP9n9oamrapheyx+3XBU/15hwQ2phq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Q4EADMZCdR5O82cqr1BhrvmzQunFdqMhEGr8368KGKb7NDyb7xnl/xHDjWu86sKIrUX+J6UMjMZnMPz3917lw+bJC9dYij/NkHMM+h3wkgn9piM/a2j5TpoXKeaRAAmQQHIEEvHQ9OFGPLW5Djeq09bL6HVVftSh/l4ZPlLsOtyo2tXL6HVVPkMSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESGKwE0oNV8aGq92uvvZaJ89wuvfTSUNd8//7918ap34wZM56NUz5lkwAJDF0CJUP31HhmJEACJEACFxIBGrQL6WrzXEmABEhgCBOgQRvCF5enRgIkQAIXEoGyOE520aJFEyD389jfg33Otm3barzaCVreS5afvNWrV5efPXt2Un9//8je3t5K6PecV72g5b1kRZF3+PDh1AMPPGAR9alPfSo1depUS1qhDg4cOOCo3/Tp0wulEtslARK4AAhEbtBqa2v/DIZiI9iN9MMvaHk/Mr3K1NXVjT19+vTMvr4+X95p0PJebUeV9+yzA9dNSFqxGLQ//OEPA05V0mjQBmBhAgmQQIQEIjVoixcvfi+M2VboVyE6ptPpdRUVFV930zdoeTc5ftNXrVo1Cp7ZLOioVvodq66ubnarH7S8m5wo02GIU889N9ChlLRbbrklVVpaGmVzgWX19PSkXnzxxQH1JO1DH/pQqry8fEAeE0iABLwJjFtx2HP188kNU1Wf5i0oZG4uPQaKT+8vSaV/MnbspHteXZvuGpgfbUpkBg3DhtKTPog9a8wQ/rapqemTMGqOFyJo+bCnnclk0suWLZuujFlZWdnZTZs2HXTTL2j5sPr5rb9r164UjHK2uPLIZAhS0iRvwYIFfkXFUk50OHXqVFa28shkCFLSJO8tb3lLLO1GJbS+vn6iyEJ4NCqZUcr5wQ9+kH0iuPPOO3uilEtZJBAPgcyM/lTmMydP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VSp27NgxTQnDMOHxMWPG7JIhQ5WmhximPIrjl5E/wDhDRzHI+6L8yr5qW7fqKo0hCZAACZBATATgVaXx+ag/QPxVWhP3whB9TR3Da6tAx38zvJp3I03iexD+BwyehPLVEFl08Uns02F85MXm38HA/Ezm4yQ/is3QU96Py3qQIhOGqhlf+zeNqXhtr7/+unx8eCSGJtNY/NGFMqcbGxuzhk7OA9tEyKrAufSgzFn8r7Y2mY+LQke7DBo0OxEekwAJkEDMBLCwYjbmop5BR69/eeNHMAir8RmpwC9Ew3B8ECr/GkaxPUrVjU9dzYNM8zNWMK5t8+fP3w+jZA59+m0TespnsdqhZ2QvU+ttm0rqiYyTAAmQAAnER+DFF188CU/lWXhWS9GK6ocvhxdzB9JHX3nllbteeuml7Ff43bQQD2r37t0LYVxkwUg9ZHVgWPBXbuXzSX/uued6r7766jfR1jhpT2QgrDx27NgE6FmKvevll1/2NE5S7+DBg6Og5wyc3xSsiOx/4YUXIjW86tzooSkSDEmABEggYQIYenwvOvxtaHaiQ9MvI+3XMFSHUOY4PCMZpqtCXIzLfKRfj/BirV4b3hObieE+c4Wilhcqavwjz1kwSOZ7bkqgzKNBl3bo143VjlmvDWkl0K0UexXSR8AbLVflEfbBEL6Uj4enyXCM0qA5YmEiCZAACSRDAP8j7WIYCvmnnjeFbHEf5q8+ijmuP4aU41hd5sNgnC6BrpbVio6FvRO78f7da1HO96nmaNAUCYYkQAIkUEAC8NZugFGThSHvCaIGvKPnUe8HMBIPyftsQermU1a8NXwJZCrqmv9ixqcc+Wr/Mby6cBw66++x+ayeuxgNWm5GLEECJEACiRFYvnz5NAzRfRBG6gPYZ6JhGY6cYChwCsbgOOIvYn8WHtm/RfmlDaMNX4F4bBhaHA19RmP14jAZjoQHp4YW+xDvRV4HzuEszuc0FoKY/4bGVwMsRAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAKDgMD/D2WyCk5hENCOAAAAAElFTkSuQmCC); + background-size: 218px 188px; + display: inline-block; + } +} + +.tui-toolbar-icons.tui-heading { + background-position: -172px -48px; +} + +.tui-toolbar-icons.tui-heading:disabled { + background-position: -193px -48px; +} + +.tui-toolbar-icons.tui-bold { + background-position: -4px -4px; +} + +.tui-toolbar-icons.tui-bold:disabled { + background-position: -25px -4px; +} + +.tui-toolbar-icons.tui-italic { + background-position: -4px -48px; +} + +.tui-toolbar-icons.tui-italic:disabled { + background-position: -25px -48px; +} + +.tui-toolbar-icons.tui-color { + background-position: -172px -70px; +} + +.tui-toolbar-icons.tui-color:disabled { + background-position: -193px -70px; +} + +.tui-toolbar-icons.tui-strike { + background-position: -4px -26px; +} + +.tui-toolbar-icons.tui-strike:disabled { + background-position: -25px -26px; +} + +.tui-toolbar-icons.tui-hrline { + background-position: -46px -92px; +} + +.tui-toolbar-icons.tui-hrline:disabled { + background-position: -67px -92px; +} + +.tui-toolbar-icons.tui-quote { + background-position: -4px -114px; +} + +.tui-toolbar-icons.tui-quote:disabled { + background-position: -25px -114px; +} + +.tui-toolbar-icons.tui-ul { + background-position: -46px -4px; +} + +.tui-toolbar-icons.tui-ul:disabled { + background-position: -67px -4px; +} + +.tui-toolbar-icons.tui-ol { + background-position: -46px -26px; +} + +.tui-toolbar-icons.tui-ol:disabled { + background-position: -67px -26px; +} + +.tui-toolbar-icons.tui-task { + background-position: -130px -48px; +} + +.tui-toolbar-icons.tui-task:disabled { + background-position: -151px -48px; +} + +.tui-toolbar-icons.tui-indent { + background-position: -46px -48px; +} + +.tui-toolbar-icons.tui-indent:disabled { + background-position: -67px -48px; +} + +.tui-toolbar-icons.tui-outdent { + background-position: -46px -70px; +} + +.tui-toolbar-icons.tui-outdent:disabled { + background-position: -67px -70px; +} + +.tui-toolbar-icons.tui-table { + background-position: -88px -92px; +} + +.tui-toolbar-icons.tui-table:disabled { + background-position: -109px -92px; +} + +.tui-toolbar-icons.tui-image { + background-position: -130px -4px; +} + +.tui-toolbar-icons.tui-image:disabled { + background-position: -151px -4px; +} + +.tui-toolbar-icons.tui-link { + background-position: -130px -26px; +} + +.tui-toolbar-icons.tui-link:disabled { + background-position: -151px -26px; +} + +.tui-toolbar-icons.tui-code { + background-position: -130px -92px; +} + +.tui-toolbar-icons.tui-code:disabled { + background-position: -151px -92px; +} + +.tui-toolbar-icons.tui-codeblock { + background-position: -130px -70px; +} + +.tui-toolbar-icons.tui-codeblock:disabled { + background-position: -151px -70px; +} + +.tui-toolbar-icons.tui-more { + background-position: -172px -92px; +} + +.tui-toolbar-icons.tui-more:disabled { + background-position: -193px -92px; +} +.tui-colorpicker-svg-slider { + border: 1px solid #ebebeb; +} +.tui-colorpicker-vml-slider { + border: 1px solid #ebebeb; +} +.tui-colorpicker-svg-huebar { + border: 1px solid #ebebeb; +} + +.tui-editor-pseudo-clipboard { + position: fixed; + left: -1000px; + top: -1000px; + width: 100px; + height: 100px; +} + +.te-ww-block-overlay.code-block-header { + text-align: right; + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +.te-ww-block-overlay.code-block-header span { + font-size: 10px; + font-weight: 600; + padding: 0px 10px; + color: #333333; + cursor: default; +} + +.te-ww-block-overlay.code-block-header button { + margin: 8px; + font-size: 10px; + color: #333333; + background-color: #f9f9f9; + border: 1px solid #dddddd; + padding: 4px; + height: auto; +} + +.te-popup-code-block-languages { + position: fixed; + box-sizing: border-box; + width: 130px; +} + +.te-popup-code-block-languages .tui-popup-body { + max-height: 169px; + overflow: auto; + padding: 0px; +} + +.te-popup-code-block-languages button { + width: 100%; + background-color: #fff; + border: none; + outline: 0; + padding: 0px 10px 0px 10px; + font-size: 12px; + line-height: 24px; + text-align: left; + color: #777; +} + +.te-popup-code-block-languages button.active { + background-color: #f4f4f4; +} + +.tui-popup-code-block-editor .tui-popup-wrapper { + width: 70%; + height: 70%; + margin: auto; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; +} + +.te-input-language { + position: relative; + margin-left: 15px; + cursor: pointer; +} + +.te-input-language input { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: 10px; + padding: 3px 5px; + border: 1px solid #dddddd; + background-color: #f9f9f9; + box-sizing: border-box; + width: 130px; + outline: none; +} + +.te-input-language input::-ms-clear { + display: none; +} + +.te-input-language::after { + content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxMnB4IiBoZWlnaHQ9IjE0cHgiIHZpZXdCb3g9IjAgMCAxMiAxNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT42Q0NBRDk2QS0yMjYxLTRFNDAtOTk1RC1DRUUyQUREQUQ3NkQ8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbS10cmFuZ2xlLWQtc2lkZSIgZmlsbD0iIzU1NTU1NSI+ICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlJlY3RhbmdsZS03IiBwb2ludHM9IjIgNSAxMCA1IDYgMTAiPjwvcG9seWdvbj4gICAgICAgIDwvZz4gICAgPC9nPjwvc3ZnPg==); + position: absolute; + top: 1px; + right: 3px; +} + +.te-input-language.active::after { + content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxMnB4IiBoZWlnaHQ9IjE0cHgiIHZpZXdCb3g9IjAgMCAxMiAxNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT5BNEZDRkIzMy0zNjdBLTREMjAtOEEyNC1DQ0I2ODFBMDZDODg8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbS10cmFuZ2xlLXVwLXNpZGUiIGZpbGw9IiM1NTU1NTUiPiAgICAgICAgICAgIDxwb2x5Z29uIGlkPSJSZWN0YW5nbGUtNyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNi4wMDAwMDAsIDYuNTAwMDAwKSBzY2FsZSgxLCAtMSkgdHJhbnNsYXRlKC02LjAwMDAwMCwgLTYuNTAwMDAwKSAiIHBvaW50cz0iMiA0IDEwIDQgNiA5Ij48L3BvbHlnb24+ICAgICAgICA8L2c+ICAgIDwvZz48L3N2Zz4=); +} + +.tui-popup-code-block-editor button { + margin: -1px 3px; +} + +.tui-popup-code-block-editor .tui-popup-header-buttons { + height: 20px; +} + +.tui-popup-code-block-editor .popup-editor-toggle-preview::after { + content: 'Preview off'; + color: #777; + margin-right: 22px; +} + +.tui-popup-code-block-editor .popup-editor-toggle-preview.active::after { + content: 'Preview on'; + color: #4b96e6; +} + +.tui-popup-code-block-editor .popup-editor-toggle-scroll::after { + content: 'Scroll off'; + color: #777; + margin-right: 16px; +} + +.tui-popup-code-block-editor .popup-editor-toggle-scroll.active::after { + content: 'Scroll on'; + color: #4b96e6; +} + +.tui-popup-code-block-editor .popup-editor-toggle-fit { + width: 18px; + height: 18px; + margin-top: 4px; + margin-right: 14px; + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCAxOCAxOCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT40OUQ4RTYyMy1GRTAyLTQ1RUUtQkQ5Ri0xMjUyQjEzRTU1MkQ8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbnRlbnRzLWV4cGFuZCIgZmlsbD0iIzU1NTU1NSI+ICAgICAgICAgICAgPHBhdGggZD0iTTMsMyBMOSwzIEw5LDUgTDUsNSBMNSw5IEwzLDkgTDMsMyBaIE0xNSwxNSBMOSwxNSBMOSwxMyBMMTMsMTMgTDEzLDkgTDE1LDkgTDE1LDE1IFoiIGlkPSJDb21iaW5lZC1TaGFwZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS4wMDAwMDAsIDkuMDAwMDAwKSBzY2FsZSgtMSwgMSkgdHJhbnNsYXRlKC05LjAwMDAwMCwgLTkuMDAwMDAwKSAiPjwvcGF0aD4gICAgICAgICAgICA8cG9seWdvbiBpZD0iTGluZSIgZmlsbC1ydWxlPSJub256ZXJvIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMS41MDAwMDAsIDYuNTAwMDAwKSBzY2FsZSgtMSwgMSkgdHJhbnNsYXRlKC0xMS41MDAwMDAsIC02LjUwMDAwMCkgIiBwb2ludHM9IjkuMDg1Nzg2NDQgNS41IDEyLjUgOC45MTQyMTM1NiAxMy45MTQyMTM2IDcuNSAxMC41IDQuMDg1Nzg2NDQiPjwvcG9seWdvbj4gICAgICAgICAgICA8cG9seWdvbiBpZD0iTGluZS1Db3B5IiBmaWxsLXJ1bGU9Im5vbnplcm8iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDYuNTAwMDAwLCAxMS41MDAwMDApIHNjYWxlKC0xLCAxKSB0cmFuc2xhdGUoLTYuNTAwMDAwLCAtMTEuNTAwMDAwKSAiIHBvaW50cz0iNC4wODU3ODY0NCAxMC41IDcuNSAxMy45MTQyMTM2IDguOTE0MjEzNTYgMTIuNSA1LjUgOS4wODU3ODY0NCI+PC9wb2x5Z29uPiAgICAgICAgPC9nPiAgICA8L2c+PC9zdmc+); +} + +.tui-popup-code-block-editor .popup-editor-toggle-fit.active { + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCAxOCAxOCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT4wN0Q1MjlCRi1GNTIzLTREN0EtQTlGNi05NTUzNTU5RDNEMUE8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbnRlbnRzLXJlZHVjZSIgZmlsbD0iIzU1NTU1NSI+ICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgtMzIiIGZpbGwtcnVsZT0ibm9uemVybyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNS41MDAwMDAsIDEyLjUwMDAwMCkgc2NhbGUoLTEsIDEpIHRyYW5zbGF0ZSgtNS41MDAwMDAsIC0xMi41MDAwMDApICIgcG9pbnRzPSIzLjA4NTc4NjQ0IDExLjUgNi41IDE0LjkxNDIxMzYgNy45MTQyMTM1NiAxMy41IDQuNSAxMC4wODU3ODY0Ij48L3BvbHlnb24+ICAgICAgICAgICAgPHBhdGggZD0iTTksOSBMMTUsOSBMMTUsMTEgTDExLDExIEwxMSwxNSBMOSwxNSBMOSw5IFogTTksOSBMMyw5IEwzLDcgTDcsNyBMNywzIEw5LDMgTDksOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMDAwMDAwLCA5LjAwMDAwMCkgc2NhbGUoLTEsIDEpIHRyYW5zbGF0ZSgtOS4wMDAwMDAsIC05LjAwMDAwMCkgIj48L3BhdGg+ICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgtMzMiIGZpbGwtcnVsZT0ibm9uemVybyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTIuNTAwMDAwLCA1LjUwMDAwMCkgc2NhbGUoLTEsIDEpIHRyYW5zbGF0ZSgtMTIuNTAwMDAwLCAtNS41MDAwMDApICIgcG9pbnRzPSIxNC45MTQyMTM2IDYuNSAxMS41IDMuMDg1Nzg2NDQgMTAuMDg1Nzg2NCA0LjUgMTMuNSA3LjkxNDIxMzU2Ij48L3BvbHlnb24+ICAgICAgICA8L2c+ICAgIDwvZz48L3N2Zz4=); +} + +.tui-popup-code-block-editor .tui-popup-close-button { + margin-top: 6px; +} + +.tui-popup-code-block-editor .tui-popup-body { + z-index: -1; + padding: 0px; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex: 1; + flex: 1; +} + +.tui-popup-code-block-editor .popup-editor-body { + position: relative; + -ms-flex: 1; + flex: 1; + border-bottom: 1px solid #cacaca; +} + +.tui-popup-code-block-editor .te-button-section { + padding: 15px; +} + +.tui-popup-code-block-editor .te-button-section button { + float: left; +} + +.tui-popup-code-block-editor .tui-editor-contents pre { + margin: 0px; + background-color: transparent; +} + +.tui-popup-code-block-editor .CodeMirror { + height: auto; +} + +.tui-popup-code-block-editor .CodeMirror-line { + font-family: Consolas, Courier, 'Apple SD 산돌고딕 Neo', -apple-system, 'Lucida Grande', + 'Apple SD Gothic Neo', '맑은 고딕', 'Malgun Gothic', 'Segoe UI', '돋움', dotum, sans-serif; + font-size: 13px; + line-height: 160%; + letter-spacing: -0.3px; +} + +.tui-popup-code-block-editor .popup-editor-editor-wrapper { + min-height: 100%; +} + +.tui-split-scroll-wrapper { + position: relative; +} + +.tui-split-scroll { + position: absolute; +} + +.tui-split-scroll, +.tui-split-scroll-wrapper { + width: 100%; + height: 100%; +} + +.tui-split-scroll .tui-split-content-left, +.tui-split-scroll .tui-split-content-right { + position: absolute; + top: 0px; + width: 50%; + box-sizing: border-box; +} + +.tui-split-scroll .tui-split-content-left { + left: 0px; +} + +.tui-split-scroll .tui-split-content-right { + left: 50%; +} + +.tui-split-scroll .tui-splitter { + position: absolute; + left: 50%; + top: 0; + height: 100%; + width: 1px; + border-left: 1px solid #cacaca; +} + +.tui-split-scroll .tui-split-scroll-content { + width: 100%; + height: 100%; + overflow: hidden; + position: relative; +} + +.tui-split-scroll .tui-split-content-left, +.tui-split-scroll .tui-split-content-right { + height: 100%; + overflow-x: hidden; + overflow-y: auto; +} + +.tui-split-scroll button.tui-scrollsync { + top: 10px; + opacity: 0.2; +} + +.tui-split-scroll button.tui-scrollsync::after { + content: 'scroll off'; +} + +.tui-split-scroll.scroll-sync button.tui-scrollsync { + opacity: 0.5; +} + +.tui-split-scroll.scroll-sync .tui-split-content-left, +.tui-split-scroll.scroll-sync .tui-split-content-right { + height: auto; + overflow: initial; +} + +.tui-split-scroll.scroll-sync button.tui-scrollsync::after { + content: 'scroll on'; +} + +.tui-split-scroll.scroll-sync .tui-split-scroll-content { + overflow-y: auto; +} + +.tui-split-scroll.single-content .tui-splitter { + display: none; +} + +.tui-split-scroll.single-content .tui-split-content-left { + width: 100%; +} + +.tui-split-scroll.single-content .tui-split-content-right { + display: none; +} + +.tui-split-scroll.single-content button.tui-scrollsync { + display: none; +} + +@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { + /* IE10+ */ + .tui-split-scroll-wrapper .tui-splitter { + left: calc(50% - 9px); + } +} + +@supports (-ms-accelerator: true) { + /* IE Edge 12+ CSS styles go here */ + .tui-split-scroll-wrapper .tui-splitter { + left: calc(50% - 9px); + } +} + +@media screen and (max-width: 480px) { + .tui-popup-wrapper { + max-width: 300px; + } + + .tui-editor-popup { + margin-left: -150px; + } + + .te-dropdown-toolbar { + max-width: none; + } +} + +@charset "utf-8"; +.CodeMirror { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +.tui-editor-contents *:not(table) { + line-height: 160%; + box-sizing: content-box; +} + +.tui-editor-contents i, +.tui-editor-contents cite, +.tui-editor-contents em, +.tui-editor-contents var, +.tui-editor-contents address, +.tui-editor-contents dfn { + font-style: italic; +} + +.tui-editor-contents strong { + font-weight: bold; +} + +.tui-editor-contents p { + margin: 10px 0; + color: #555; +} + +.tui-editor-contents > h1:first-of-type, +.tui-editor-contents > div > div:first-of-type h1 { + margin-top: 14px; +} + +.tui-editor-contents h1, +.tui-editor-contents h2, +.tui-editor-contents h3, +.tui-editor-contents h5 { + font-weight: bold; +} + +.tui-editor-contents h1 { + font-size: 1.6rem; + line-height: 28px; + border-bottom: 3px double #999; + margin: 52px 0 15px 0; + padding-bottom: 7px; + color: #000; +} + +.tui-editor-contents h2 { + font-size: 1.3rem; + line-height: 23px; + border-bottom: 1px solid #dbdbdb; + margin: 30px 0 13px 0; + padding-bottom: 7px; + color: #333; +} + +.tui-editor-contents h3, +.tui-editor-contents h4 { + font-size: 1.2rem; + line-height: 18px; + margin: 20px 0 2px; + color: #333; +} + +.tui-editor-contents h5, +.tui-editor-contents h6 { + font-size: 1rem; + line-height: 17px; + margin: 10px 0 -4px; + color: #333; +} + +.tui-editor-contents blockquote { + margin: 15px 0; +} + +.tui-editor-contents blockquote { + border-left: 4px solid #dddddd; + padding: 0 15px; + color: #777777; +} + +.tui-editor-contents blockquote > :first-child { + margin-top: 0; +} + +.tui-editor-contents blockquote > :last-child { + margin-bottom: 0; +} + +.tui-editor-contents pre, +.tui-editor-contents code { + font-family: Consolas, Courier, 'Lucida Grande', '나눔바른고딕', 'Nanum Barun Gothic', '맑은고딕', + 'Malgun Gothic', sans-serif; + border: 0; + border-radius: 0; +} + +.tui-editor-contents pre { + margin: 2px 0 8px; + padding: 18px; + background-color: #f5f7f8; +} + +.tui-editor-contents code { + color: #c1788b; + padding: 4px 4px 2px 0; + letter-spacing: -0.3px; +} + +.tui-editor-contents pre code { + padding: 0; + color: inherit; + white-space: pre-wrap; + background-color: transparent; +} + +.tui-editor-contents pre.addon { + border: 1px solid #e8ebed; + background-color: #fff; +} + +.tui-editor-contents img { + margin: 4px 0 10px; + box-sizing: border-box; + vertical-align: top; + max-width: 100%; +} + +.tui-editor-contents table { + margin: 2px 0 14px; + color: #555; + width: auto; + border-collapse: collapse; + box-sizing: border-box; +} + +.tui-editor-contents table th, +.tui-editor-contents table td { + height: 32px; + padding: 5px 14px 5px 12px; +} + +.tui-editor-contents table td { + border: 1px solid #eaeaea; +} + +.tui-editor-contents table th { + border: 1px solid #72777b; + border-top: 0; + background-color: #7b8184; + font-weight: 300; + color: #fff; + padding-top: 6px; +} + +.tui-editor-contents ul, +.tui-editor-contents menu, +.tui-editor-contents ol, +.tui-editor-contents dir { + display: block; + list-style-type: disc; + padding-left: 17px; + margin: 6px 0 10px; + color: #555; +} + +.tui-editor-contents ol { + list-style-type: decimal; +} + +.tui-editor-contents ul ul, +.tui-editor-contents ul ol, +.tui-editor-contents ol ol, +.tui-editor-contents ol ul { + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +.tui-editor-contents ul li, +.tui-editor-contents ol li { + position: relative; +} + +.tui-editor-contents ul p, +ol p { + margin: 0; +} + +.tui-editor-contents ul li.task-list-item:before, +.tui-editor-contents ol li.task-list-item:before, +.tui-editor-contents pre ul li:before { + content: ''; +} + +.tui-editor-contents hr { + border-top: 1px solid #eee; + margin: 16px 0; +} + +.tui-editor-contents a { + text-decoration: underline; + color: #5286bc; +} + +.tui-editor-contents a:hover { + color: #007cff; +} + +.tui-editor-contents a.image-link { + position: relative; +} + +.tui-editor-contents a.image-link::before { + content: ''; + position: absolute; + margin: 0; + width: 20px; + height: 20px; + top: 2px; + right: 2px; + background-repeat: no-repeat; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAFKADAAQAAAABAAAAFAAAAACy3fD9AAAA/0lEQVQ4Ee2UIY6FQAyG/91wAQQJDg8SSwI3QIFAcQHuwFHQoOAEEFAELB6H4wIku+9vQgIP9zLyVbTTTufLtJ3MzzRNf1AoGlmu6ypBzvOMXyWkC+QLvDTjw6VM+Xr2OA6UZYmu67Dvu2zleX6zuq7D933EcQxNuyPu3usYYXVdw/M8mKYpIMMwxEZRJHbbNsmhkySJxE71APJmhGVZhnVdURQFlmU585GmKSzLEp+570Dlz+ZxQ/aGJVNYsm3bCIJA/LZtMY4jmqbBMAwIw1DiV/UAstEUltP3vawdxxFbVZVYDoWwM1eCp+LnoErIUt7DL/Ac1edWng1/WlXyD380myY5A34sAAAAAElFTkSuQmCC'); + cursor: pointer; +} + +.tui-editor-contents { + font-size: 13px; + margin: 0; + padding: 0; +} + +.tui-editor-contents .task-list-item { + border: 0; + list-style: none; + padding-left: 22px; + margin-left: -22px; + min-height: 20px; +} + +.tui-editor-contents .task-list-item:before { + background-repeat: no-repeat; + background-size: 16px 16px; + background-position: center; + content: ''; + height: 18px; + width: 18px; + position: absolute; + left: 0; + top: 1px; + cursor: pointer; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAADdJREFUKBVjvHv37n8GMgALSI+SkhJJWu/du8fARJIOJMWjGpECA505GjjoIYLEB6dVUNojFQAA/1MJUFWet/4AAAAASUVORK5CYII='); +} + +.tui-editor-contents .task-list-item.checked:before { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAMpJREFUKBVjjJ/64D8DGYCJDD1gLbTVyM3OxJDiJMzAxcYIdyALnIWDAdJU7i/OICfCxsDMxMgwc88bwk5F1vTs/W+GFUffwY2H+1FBlI2hLliCQYCbGSyJrqlzwwuGj9//YWoMtRBgUBJnZ6gMEGeQFWaFOw9kE7omkG5GWDyCPF7mJ86gIMbO8P//fwZGRkYGXJpAGuFO/fbrP0PXppcMD179JKgJRSOIA9N8/NZXrM4DqYEBjOgAaYYFOUwRNhruVGyS+MTI1ggAx8NTGcUtFVQAAAAASUVORK5CYII='); +} + +.tui-editor-contents .task-list-item input[type='checkbox'], +.tui-editor-contents .task-list-item .task-list-item-checkbox { + margin-left: -17px; + margin-right: 3.8px; + margin-top: 3px; +} + +.tui-editor-contents-placeholder:before { + content: attr(data-placeholder); + color: grey; + line-height: 160%; + position: absolute; +} + +.tui-editor-contents .te-preview-highlight { + position: relative; + z-index: 0; +} + +.tui-editor-contents .te-preview-highlight::after { + content: ''; + background-color: rgba(255, 245, 131, 0.5); + border-radius: 4px; + z-index: -1; + position: absolute; + top: -4px; + right: -4px; + left: -4px; + bottom: -4px; +} + +.tui-editor-contents h1.te-preview-highlight::after, +.tui-editor-contents h2.te-preview-highlight::after { + bottom: 0; +} + +.tui-editor-contents td.te-preview-highlight::after, +.tui-editor-contents th.te-preview-highlight::after { + display: none; +} + +.tui-editor-contents th.te-preview-highlight, +.tui-editor-contents td.te-preview-highlight { + background-color: rgba(255, 245, 131, 0.5); +} + +.tui-editor-contents th.te-preview-highlight { + color: #222; +} + +.te-md-container .CodeMirror { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #000; +} + +.tui-md-heading1 { + font-size: 24px; +} + +.tui-md-heading2 { + font-size: 22px; +} + +.tui-md-heading3 { + font-size: 20px; +} + +.tui-md-heading4 { + font-size: 18px; +} + +.tui-md-heading5 { + font-size: 16px; +} + +.tui-md-heading6 { + font-size: 14px; +} + +.tui-md-strong, +.tui-md-heading { + font-weight: bold; +} + +.tui-md-emph { + font-style: italic; +} + +.tui-md-strike { + text-decoration: line-through; +} + +.tui-md-thematic-break { + color: #ccc; +} + +.tui-md-link.tui-md-link-desc { + color: #00c; +} + +.tui-md-link.tui-md-link-url { + color: #a11; +} + +.tui-md-block-quote { + color: #090; +} + +.tui-md-code, +.tui-md-code-block { + color: #a50; +} + +.tui-md-list-item.first { + color: #000; +} + +.tui-md-list-item.second { + color: #085; +} + +.tui-md-list-item.third { + color: #708; +} + +.tui-md-list-item.tui-md-delimiter { + color: #555; +} + diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-only.css b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-only.css new file mode 100644 index 0000000000..4d62f7c2c9 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-only.css @@ -0,0 +1,1433 @@ +/*! + * @toast-ui/editor + * @version 2.5.1 | Tue Nov 24 2020 + * @author NHN FE Development Lab + * @license MIT + */ +@charset "utf-8"; +/* height */ +.auto-height, +.auto-height .tui-editor-defaultUI { + height: auto; +} + +.auto-height .tui-editor { + position: relative; +} + +:not(.auto-height) > .tui-editor-defaultUI, +:not(.auto-height) > .tui-editor-defaultUI > .te-editor-section { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; +} + +:not(.auto-height) > .tui-editor-defaultUI > .te-editor-section { + -ms-flex: 1; + flex: 1; +} + +/* tui editor */ +.tui-editor:after, +.tui-editor-defaultUI-toolbar:after { + content: ''; + display: block; + height: 0; + clear: both; +} + +.tui-editor { + position: absolute; + line-height: 1; + color: #222; + width: 100%; + height: inherit; +} + +.te-editor-section { + min-height: 0px; + position: relative; + height: inherit; +} + +.te-md-container { + display: none; + overflow: hidden; + height: 100%; +} + +.te-md-container .te-editor { + line-height: 1.5; +} + +.te-md-container .te-editor, +.te-md-container .te-preview { + box-sizing: border-box; + padding: 0; + height: inherit; +} + +.te-md-container .CodeMirror { + font-size: 13px; + height: inherit; +} + +.te-md-container .te-preview { + overflow: auto; + padding: 0 25px; + height: 100%; +} + +.te-md-container .te-preview > p:first-child { + margin-top: 0 !important; +} + +.te-md-container .te-preview .tui-editor-contents { + padding-top: 8px; +} + +.tui-editor .te-preview-style-tab > .te-editor, +.tui-editor .te-preview-style-tab > .te-preview { + float: left; + width: 100%; + display: none; +} + +.tui-editor .te-preview-style-tab > .te-tab-active { + display: block; +} + +.tui-editor .te-preview-style-vertical > .te-tab-section { + display: none; +} + +.tui-editor .te-preview-style-tab > .te-tab-section { + display: block; +} + +.tui-editor .te-preview-style-vertical .te-editor { + float: left; + width: 50%; +} + +.tui-editor .te-preview-style-vertical .te-preview { + float: left; + width: 50%; +} + +.tui-editor .te-md-splitter { + display: none; + position: absolute; + left: 50%; + top: 0; + height: 100%; + width: 1px; + border-left: 1px solid #e5e5e5; +} + +.tui-editor .te-preview-style-vertical .te-md-splitter { + display: block; +} + +.te-ww-container { + display: none; + overflow: hidden; + z-index: 10; + height: inherit; + background-color: #fff; +} + +.te-ww-container > .te-editor { + overflow: auto; + height: inherit; +} + +.te-ww-container .tui-editor-contents:focus { + outline: none; +} + +.te-ww-container .tui-editor-contents { + padding: 0 25px; +} + +.te-ww-container .tui-editor-contents:first-child { + box-sizing: border-box; + margin: 0px; + padding: 16px 25px 0px 25px; + height: inherit; +} + +.te-ww-container .tui-editor-contents:last-child { + margin-bottom: 16px; +} + +.te-md-mode .te-md-container { + display: block; + z-index: 100; +} + +.te-ww-mode .te-ww-container { + display: block; + z-index: 100; +} + +.tui-editor.te-hide, +.tui-editor-defaultUI.te-hide { + display: none; +} + +.tui-editor-defaultUI .CodeMirror-lines { + padding-top: 18px; + padding-bottom: 18px; +} + +.tui-editor-defaultUI pre.CodeMirror-line { + padding-left: 25px; + padding-right: 25px; +} + +.tui-editor-defaultUI .CodeMirror pre.CodeMirror-placeholder { + margin: 0; + padding-left: 25px; + color: grey; +} + +.tui-editor-defaultUI .CodeMirror-scroll { + cursor: text; +} + +/* Essential element style */ +.tui-editor-contents td.te-cell-selected { + background-color: #d8dfec; +} +.tui-editor-contents td.te-cell-selected::selection { + background-color: #d8dfec; +} +.tui-editor-contents th.te-cell-selected { + background-color: #908f8f; +} +.tui-editor-contents th.te-cell-selected::selection { + background-color: #908f8f; +} + +/* default UI Styles */ +.tui-editor-defaultUI { + position: relative; + border: 1px solid #e5e5e5; + height: 100%; + font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', 'Arial', '나눔바른고딕', + 'Nanum Barun Gothic', '맑은고딕', 'Malgun Gothic', sans-serif; +} + +.tui-editor-defaultUI button { + color: #fff; + padding: 0px 14px 0px 15px; + height: 28px; + font-size: 12px; + border: none; + cursor: pointer; + outline: none; +} +.tui-editor-defaultUI button.te-ok-button { + background-color: #4b96e6; +} +.tui-editor-defaultUI button.te-close-button { + background-color: #777; +} + +.tui-editor-defaultUI-toolbar { + padding: 0 25px; + height: 31px; + background-color: #fff; + border: 0; + overflow: hidden; +} + +.tui-toolbar-divider { + float: left; + display: inline-block; + width: 1px; + height: 14px; + background-color: #ddd; + margin: 9px 6px; +} + +.tui-toolbar-button-group { + height: 28px; + border-right: 1px solid #d9d9d9; + float: left; +} + +.te-toolbar-section { + height: 32px; + box-sizing: border-box; + border-bottom: 1px solid #e5e5e5; +} + +.tui-editor-defaultUI-toolbar button { + float: left; + box-sizing: border-box; + outline: none; + cursor: pointer; + background-color: #fff; + width: 22px; + height: 22px; + padding: 3px; + border-radius: 0; + margin: 5px 3px; + border: 1px solid #fff; +} + +.tui-editor-defaultUI-toolbar button:hover, +.tui-editor-defaultUI-toolbar button:active, +.tui-editor-defaultUI-toolbar button.active { + border: 1px solid #aaa; + background-color: #fff; +} + +.tui-editor-defaultUI-toolbar button:first-child { + margin-left: 0; +} + +.tui-editor-defaultUI-toolbar button:last-child { + margin-right: 0; +} + +.tui-editor-defaultUI-toolbar button.tui-scrollsync { + width: auto; + color: #777777; + border: 0; +} + +.tui-editor-defaultUI button.tui-scrollsync:after { + content: 'Scroll off'; +} + +.tui-editor-defaultUI button.tui-scrollsync.active { + color: #4b96e6; + font-weight: bold; +} + +.tui-editor-defaultUI button.tui-scrollsync.active:after { + content: 'Scroll on'; +} + +.tui-editor-defaultUI .te-mode-switch-section { + background-color: #f9f9f9; + border-top: 1px solid #e5e5e5; + height: 20px; + font-size: 12px; +} + +.tui-editor-defaultUI .te-mode-switch { + float: right; + height: 100%; +} + +.tui-editor-defaultUI .te-switch-button { + width: 92px; + height: inherit; + background: #e5e5e5; + outline: 0; + color: #a0aabf; + cursor: pointer; + border: 0; + border-left: 1px solid #ddd; + border-right: 1px solid #ddd; +} + +.tui-editor-defaultUI .te-switch-button.active { + background-color: #fff; + color: #000; +} + +.tui-editor-defaultUI .te-markdown-tab-section { + float: left; + height: 31px; + background: #fff; +} + +.te-markdown-tab-section .te-tab { + margin: 0 -7px 0 24px; + background: #fff; +} + +.tui-editor-defaultUI .te-tab button { + box-sizing: border-box; + line-height: 100%; + position: relative; + cursor: pointer; + z-index: 1; + font-size: 13px; + background-color: #f9f9f9; + border: solid 1px #e5e5e5; + border-top: 0; + padding: 0 9px; + color: #777; + border-radius: 0; + outline: 0; +} + +.te-markdown-tab-section .te-tab button:last-child { + margin-left: -1px; +} + +.te-markdown-tab-section .te-tab button.te-tab-active, +.te-markdown-tab-section .te-tab button:hover.te-tab-active { + background-color: #fff; + color: #333; + border-bottom: 1px solid #fff; + z-index: 2; +} + +.te-markdown-tab-section .te-tab button:hover { + background-color: #fff; + color: #333; +} + +.tui-popup-modal-background { + background-color: rgba(202, 202, 202, 0.6); + position: fixed; + margin: 0px; + left: 0px; + top: 0px; + width: 100%; + height: 100%; + z-index: 9999; +} + +.tui-popup-wrapper.fit-window, +.tui-popup-modal-background.fit-window .tui-popup-wrapper { + width: 100%; + height: 100%; +} + +.tui-popup-wrapper { + width: 500px; + margin-right: auto; + border: 1px solid #cacaca; + background: white; + z-index: 9999; +} + +.tui-popup-modal-background .tui-popup-wrapper { + position: absolute; + margin: auto; + top: 0px; + right: 0px; + bottom: 0px; + left: 0px; +} + +.tui-popup-header { + padding: 10px; + height: auto; + line-height: normal; + position: relative; + border-bottom: 1px solid #cacaca; +} + +.tui-popup-header .tui-popup-header-buttons { + float: right; +} + +.tui-popup-header .tui-popup-header-buttons button { + padding: 0px; + background-color: transparent; + background-size: cover; + float: left; +} + +.tui-popup-header .tui-popup-close-button { + margin: 3px; + width: 13px; + height: 13px; + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxMHB4IiBoZWlnaHQ9IjEwcHgiIHZpZXdCb3g9IjAgMCAxMCAxMCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT5GMjc2Qzc4MC0zM0JBLTQ3MTItQTM3OC04RkQwQUNDOTFDRTk8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImxuYi1mb2xkZXItZGVsIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGZpbGw9IiM3Nzc3NzciPiAgICAgICAgICAgIDxwYXRoIGQ9Ik01LDMuNTg1Nzg2NDQgTDEuNzA3MTA2NzgsMC4yOTI4OTMyMTkgTDAuMjkyODkzMjE5LDEuNzA3MTA2NzggTDMuNTg1Nzg2NDQsNSBMMC4yOTI4OTMyMTksOC4yOTI4OTMyMiBMMS43MDcxMDY3OCw5LjcwNzEwNjc4IEw1LDYuNDE0MjEzNTYgTDguMjkyODkzMjIsOS43MDcxMDY3OCBMOS43MDcxMDY3OCw4LjI5Mjg5MzIyIEw2LjQxNDIxMzU2LDUgTDkuNzA3MTA2NzgsMS43MDcxMDY3OCBMOC4yOTI4OTMyMiwwLjI5Mjg5MzIxOSBMNSwzLjU4NTc4NjQ0IFoiIGlkPSJDb21iaW5lZC1TaGFwZSI+PC9wYXRoPiAgICAgICAgPC9nPiAgICA8L2c+PC9zdmc+); +} + +.tui-popup-header .tui-popup-title { + font-size: 13px; + font-weight: bold; + color: #333; + vertical-align: bottom; +} + +.tui-popup-body { + padding: 15px; + font-size: 12px; +} + +.tui-editor-popup { + position: absolute; + top: 30px; + left: 50%; + margin-left: -250px; +} + +.tui-editor-popup.tui-popup-modal-background { + position: fixed; + top: 0px; + left: 0px; + margin: 0px; +} + +.tui-editor-popup .tui-popup-body label { + font-weight: bold; + color: #666; + display: block; + margin: 10px 0 5px; +} + +.tui-editor-popup .tui-popup-body .te-button-section { + margin-top: 15px; +} + +.tui-editor-popup .tui-popup-body input[type='text'], +.tui-editor-popup .tui-popup-body input[type='file'] { + padding: 4px 10px; + border: 1px solid #bfbfbf; + box-sizing: border-box; + width: 100%; +} + +.tui-editor-popup .tui-popup-body input[type='text'].disabled { + border-color: #e5e5e5; + background-color: #eee; + color: #e5e5e5; +} + +.tui-editor-popup .tui-popup-body input.wrong { + border-color: #ff0000; +} + +.te-popup-add-link .tui-popup-wrapper { + height: 219px; +} + +.te-popup-add-image .tui-popup-wrapper { + height: 243px; +} + +.te-popup-add-image .te-tab { + display: block; + background: none; + border-bottom: 1px solid #ebebeb; + margin-bottom: 8px; +} + +.te-popup-add-image .te-url-type { + display: none; +} + +.te-popup-add-image .te-file-type { + display: none; +} + +.te-popup-add-image div.te-tab-active, +.te-popup-add-image form.te-tab-active { + display: block; +} + +.te-popup-add-image .te-tab button { + border: 1px solid #ccc; + background: #eee; + min-width: 100px; + margin-left: -1px; + border-bottom: 0px; + border-radius: 3px 3px 0px 0px; +} + +.te-popup-add-image .te-tab button.te-tab-active { + background: #fff; +} + +.te-popup-add-table .te-table-selection { + position: relative; +} + +.te-popup-add-table .te-table-body { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAARCAYAAAAougcOAAAC7mlDQ1BJQ0MgUHJvZmlsZQAAeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFkifEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UXAeIuJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOklEQVQ4EWO8e/fuPwYGBkYgphlgAZmspKREMwtABjPR1HSo4aOWkBTKo8E1GlwkhQBJikdT1wgNLgAMSwQgckFvTgAAAABJRU5ErkJggg=='); +} + +.te-popup-add-table .te-table-header { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAARCAYAAAAougcOAAAC7mlDQ1BJQ0MgUHJvZmlsZQAAeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFkifEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UXAeIuJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOklEQVQ4EWO8e/fuPwYGBkYgphlgAZksLCxMMwtABjPR1HSo4aOWkBTKo8E1GlwkhQBJikdT1wgNLgDxKwPzTeWPdAAAAABJRU5ErkJggg=='); +} + +.te-popup-add-table .te-selection-area { + position: absolute; + top: 0; + left: 0; + background: #80d2ff; + opacity: 0.3; + z-index: 999; +} + +.te-popup-add-table .te-description { + margin: 10px 0 0 0; + text-align: center; +} + +.te-popup-table-utils { + width: auto; + min-width: 120px; +} + +.te-popup-table-utils .tui-popup-body { + padding: 0px; +} + +.te-popup-table-utils button { + display: block; + width: 100%; + background-color: #fff; + border: none; + outline: 0; + padding: 0px 10px 0px 10px; + font-size: 12px; + line-height: 28px; + text-align: left; + color: #777; +} + +.te-popup-table-utils button:hover { + background-color: #f4f4f4; +} + +.te-popup-table-utils hr { + margin: 0; + background-color: #cacaca; + border-style: none; + height: 1px; +} + +.te-popup-table-utils .te-context-menu-disabled { + color: #ccc; +} + +.te-popup-table-utils .te-context-menu-disabled:hover { + background-color: #fff; +} + +.te-heading-add { + width: auto; +} + +.te-heading-add .tui-popup-body { + padding: 0; +} + +.te-heading-add h1, +.te-heading-add h2, +.te-heading-add h3, +.te-heading-add h4, +.te-heading-add h5, +.te-heading-add h6, +.te-heading-add ul, +.te-heading-add p { + padding: 0; + margin: 0; +} + +.te-heading-add ul { + list-style: none; +} + +.te-heading-add ul li { + padding: 2px 10px; + cursor: pointer; +} + +.te-heading-add ul li:hover { + background-color: #eee; +} + +.te-heading-add h1 { + font-size: 24px; +} + +.te-heading-add h2 { + font-size: 22px; +} + +.te-heading-add h3 { + font-size: 20px; +} + +.te-heading-add h4 { + font-size: 18px; +} + +.te-heading-add h5 { + font-size: 16px; +} + +.te-heading-add h6 { + font-size: 14px; +} + +.te-dropdown-toolbar { + position: absolute; + width: auto; +} + +.te-dropdown-toolbar .tui-popup-body { + padding: 0px; +} + +.tui-popup-color { + padding: 0; +} + +.tui-popup-color .tui-colorpicker-container, +.tui-popup-color .tui-colorpicker-palette-container { + width: 144px; +} + +.tui-popup-color .tui-colorpicker-container ul { + width: 144px; + margin-bottom: 8px; +} + +.tui-popup-color .tui-colorpicker-container li { + padding: 0 1px 1px 0; +} + +.tui-popup-color .tui-colorpicker-container li .tui-colorpicker-palette-button { + border: 0; + width: 17px; + height: 17px; +} + +.tui-popup-color .tui-popup-body { + padding: 10px; +} + +.tui-popup-color .tui-colorpicker-container .tui-colorpicker-palette-toggle-slider { + display: none; +} + +.tui-popup-color .te-apply-button, +.tui-popup-color .tui-colorpicker-palette-hex { + float: right; +} + +.tui-popup-color .te-apply-button { + height: 21px; + width: 35px; + background: #fff; + border: 1px solid #efefef; + position: absolute; + bottom: 135px; + right: 10px; + color: black; +} + +.tui-popup-color .tui-colorpicker-container .tui-colorpicker-palette-hex { + border: 1px solid #e1e1e1; + padding: 3px 14px; + margin-left: -1px; +} + +.tui-popup-color .tui-colorpicker-container div.tui-colorpicker-clearfix { + display: inline-block; +} + +.tui-popup-color .tui-colorpicker-container .tui-colorpicker-palette-preview { + width: 19px; + height: 19px; +} + +.tui-popup-color .tui-colorpicker-slider-container .tui-colorpicker-slider-right { + width: 22px; +} + +.tui-popup-color .tui-colorpicker-slider-container .tui-colorpicker-huebar-handle { + display: none; +} + +.tui-tooltip { + position: absolute; + background-color: #222; + z-index: 999; + opacity: 0.8; + color: #fff; + padding: 2px 5px; + font-size: 10px; +} + +.tui-tooltip .arrow { + content: ''; + display: inline-block; + width: 10px; + height: 10px; + background-color: #222; + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); + position: absolute; + top: -3px; + left: 6px; + z-index: -1; +} + +.tui-toolbar-icons { + background: url(data:image/png;base64,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); + background-size: 218px 188px; + display: inline-block; +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), + only screen and (min--moz-device-pixel-ratio: 2), + only screen and (-o-min-device-pixel-ratio: 2/1), + only screen and (min-device-pixel-ratio: 2), + only screen and (min-resolution: 192dpi), + only screen and (min-resolution: 2dppx) { + .tui-toolbar-icons { + background: url(data:image/png;base64,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Xqz8qBcJkED0BGIbcoxe1QtDor4qT80zFpNh01flYWg2e1Fo2C6Me5NnSQLFToAeWpFfITFmxbrCUdCJMeMKxyK/iageCZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACQQgkA5QNlTRRYsWZbwEbNu2LTFdnPSAftc6pas06PesihdTmIurXdekOefi6qBfpJyD8rHrk+s4LM+gfHLpY8+P+r6Ngmc6nf7q1q1b6+26RnEcBc/S0tLmLVu2HI5Cn6Ay7Hxz3V9BywfVx17ezjfX/RW0vL29oMclQSuwPAmQAAnkS0A3ZrW1tR9Gh1ebr6w46unGrK6ubiz0GxdHO5QZD4HEDJo8aeBmmWk7jf2SnuspxFYnlkN50pg8efJLNuHdki67LZ2HJEACAQnYjVl/f/+PIeLxYjFqdmPW0dExC/rNpFELeKELWDwxgybn2NfXt1A/V9zg2/XjQsePHz8+StcBN/gZ/ZhxEiCB/Ai4GLMKSCvFXnCj5mTMYHDVNAiNWn6XPfFaZUm2iJt6YSZzfioN8e1Jtp+rLegzUi8Dfdv14yTiixcvbhw7duxdDQ0Nb/ppL2nvdsmSJZfMmzfvQH19fb9P/Qrq3SbNxw8Tvcxg9/6D8pVhRsMzE2OmthJslodJlRE2DMpXhhnFM9OMWVaFsrKyRB/+w573hVo/0YsEg7FQB42nou36caHj8CAtP6qamprEPTQwuq21tfX3GOa4vNA8nNoHo/G7d++eD/2qnPKZRgJuBFyMWQbGbHVTU9NDbvWSSvcwZvs3b958PCk92E7+BBIzaPJkDzVnaKrux0qi17XjgkbXrFkzDAroT43da9eu7SqQUmLMxKjVFah9z2Z7e3sr8TAyb+nSpTWeBZl5wRGQewKjDP/bfuLFYswwslAmhsuuH42ZncjgPE7MoHH+LPANMhw1HpUhyNWrV0u8qDZczxIYthnyoIJOIrH7qKggUBkLATFmuCf+E4k/xsPYCpVZTMZsx44dc86ePXvpypUrxyv9aMwUicEfJjaHxvmz/G4WYwjyOnQQizAf8LJdCpLPT0raMx2Og855OIiwJBlDkCOgx17I7rBk4gDpnu/32csHnfOw1w96HJSfXX7UPO3yg/Kz10+Kp2bMrsQ9m8LvvRG6pzCc2OowZ5b4MKN4ZmLMwCc7VI55sktg1ES/Ppc5s6IYZgx7f9rvh6iPw96fUeuT2JM1589CXToOQYbCx8pxE8CDzbUwYvNVO/i9l4hRKwZjJjrBmI2A8apU+kkoRq2YjZmuK+P+CCRi0Dh/5u9i5CqFDiKQN5ZLXtT55eXlRa1f1OdLeecJ4Msfv4ARq8U92qNSxaghrs9LO3pmGFavV3XiCuGpnsK87z4YNcs96rCacYBnhv5ralx6UW60BBIxaJw/C33RZKjxOnQaj4WWFIMALGnuxDXetX79+hMxiKfIQUIARuMJu1HTVHc1Zqhzr1YutuimTZtanYyaahD3saMxw709RZVhWNwEEplDw1Mb3z/L8z4Au8e83kuLew4nl9roIE7MnTvX9b20pOZwcunpll9ofm56qfRi56f0VCH0fQLzKrIg5HHs8tJ0doNn9En70nzxzJIyZkoPMWrQT16Ytny1qLKy8uCGDRssS/PFMyu0Mct1fxZ6ji3X/Zn0HFsiBg037UJ1Q0mITnC7flzoOG7agr9/5sDgTRizu4rVK8M17K+oqDhAr8zhyl3gSejkmtCRCYWsUYMx+wSM2TodSyGMmWof+p009MsaNcOYHVX5EhaDMdP1YdwfgdiHHDl/5u9C2EpxiNEGhIeDi4AYNWi83MmYyZkk7ZnZ6YlRQ9o+J2MmZQvtmdn15bE/ArF7aLgxFuqqwOvYrh8XOl5s32/MNcRYaF65hhgLrR/bLx4ChlErHoVsmhhGzZbKw8FMIHaDhg6a82cB7hAMMdYFKC7veVlWbeWqix+xzB/kvQX9ukvQMXTo92zeyjlUDMrHQYRnUlieQfl4KuOQGTVPexNx87W3F/Q4br5B9WH5eAnEPuTI+bN4LyClkwAJkAAJnCMQm4fm9uSGIch9yEuFfbINewHdntxaWlquMPSL1FMIqy/rkwAJkAAJeBOI3UPzbp65JEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJFC8BNJRq7Zo0aKMLnPbtm2ebQQtr8vOJ472rtXrQb9n9WN7PGh5e/24j+38crWX63rkqh80384vV/1c1yNXfXt+UD72+rmOw/IMyieXPvb8qHkq+dB7TDqdvgPHtZlMZrak4/gVBE04fgjtnpI0tfm4Ds2ov728vPwLjz/++CFVL98Q7ZWWlZXV9Pf3j8M+TOSUlJR0YT/Z29t7HPr16bJzXQfI6oF+7T09PYdQt1uvG1fc0Om/bfLf5nRNX5xytaXftdVJvaX5j579sL28n+MVK1aM6OzsnKeXrays3LVhw4azeprEd065xtLv2vPnN//Bsx+2l3c7LnHLYDoJkAAJOBFYvHjxDUh/CYbrO9ivQ3ys7BKXNMkzyiDqe5uCuku7u7ufX758+TTftRwKrlq1ahQM0AIYrmkwZsNRpFR2iUua5EkZh6quSahXDmNWjQKXw9BUuBaMMAMG9E67OKc0e5mkjvv6+mrsbTml2cvEeUyDFiddyiaBIUYAnfn7YXh+jtPyMjrTpMySJUv+Zx6nPw6G4+/yqJetAmM4+uzZs7PFALnJkDwpI2Xdynikl8KL9Dp3j6r+s8B5pBh4ew1Jkzx7etLH0EEeEMbZ25U0ybOnJ3VMg5YUabZDAoOcwK233joFHkITTiM7hOd1Oij3Mzytv+BVxiPvfR55rlmrV68uh4c3C51qzuG10tLSthEjRnS4CvPIgFFJwqAsgwrZdsDy97IbKkma5BV6G4frm7UfGMZ9U3ZRyEgbYOiSUrYsqYbYTjgC+LEOb2trW7d169Y6XRLG03P+ePXyccXr6+tLdu3aNX3Lli2v6204jffr+XHHi4WP23kWmo+bXk7pMBb3ozOXYTd9a0Rn9nUM4x1D/v9Ax3sP9n9oamrapheyx+3XBU/15hwQ2phq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Q4EADMZCdR5O82cqr1BhrvmzQunFdqMhEGr8368KGKb7NDyb7xnl/xHDjWu86sKIrUX+J6UMjMZnMPz3917lw+bJC9dYij/NkHMM+h3wkgn9piM/a2j5TpoXKeaRAAmQQHIEEvHQ9OFGPLW5Djeq09bL6HVVftSh/l4ZPlLsOtyo2tXL6HVVPkMSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESGKwE0oNV8aGq92uvvZaJ89wuvfTSUNd8//7918ap34wZM56NUz5lkwAJDF0CJUP31HhmJEACJEACFxIBGrQL6WrzXEmABEhgCBOgQRvCF5enRgIkQAIXEoGyOE520aJFEyD389jfg33Otm3barzaCVreS5afvNWrV5efPXt2Un9//8je3t5K6PecV72g5b1kRZF3+PDh1AMPPGAR9alPfSo1depUS1qhDg4cOOCo3/Tp0wulEtslARK4AAhEbtBqa2v/DIZiI9iN9MMvaHk/Mr3K1NXVjT19+vTMvr4+X95p0PJebUeV9+yzA9dNSFqxGLQ//OEPA05V0mjQBmBhAgmQQIQEIjVoixcvfi+M2VboVyE6ptPpdRUVFV930zdoeTc5ftNXrVo1Cp7ZLOioVvodq66ubnarH7S8m5wo02GIU889N9ChlLRbbrklVVpaGmVzgWX19PSkXnzxxQH1JO1DH/pQqry8fEAeE0iABLwJjFtx2HP188kNU1Wf5i0oZG4uPQaKT+8vSaV/MnbspHteXZvuGpgfbUpkBg3DhtKTPog9a8wQ/rapqemTMGqOFyJo+bCnnclk0suWLZuujFlZWdnZTZs2HXTTL2j5sPr5rb9r164UjHK2uPLIZAhS0iRvwYIFfkXFUk50OHXqVFa28shkCFLSJO8tb3lLLO1GJbS+vn6iyEJ4NCqZUcr5wQ9+kH0iuPPOO3uilEtZJBAPgcyM/lTmMydP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VSp27NgxTQnDMOHxMWPG7JIhQ5WmhximPIrjl5E/wDhDRzHI+6L8yr5qW7fqKo0hCZAACZBATATgVaXx+ag/QPxVWhP3whB9TR3Da6tAx38zvJp3I03iexD+BwyehPLVEFl08Uns02F85MXm38HA/Ezm4yQ/is3QU96Py3qQIhOGqhlf+zeNqXhtr7/+unx8eCSGJtNY/NGFMqcbGxuzhk7OA9tEyKrAufSgzFn8r7Y2mY+LQke7DBo0OxEekwAJkEDMBLCwYjbmop5BR69/eeNHMAir8RmpwC9Ew3B8ECr/GkaxPUrVjU9dzYNM8zNWMK5t8+fP3w+jZA59+m0TespnsdqhZ2QvU+ttm0rqiYyTAAmQAAnER+DFF188CU/lWXhWS9GK6ocvhxdzB9JHX3nllbteeuml7Ff43bQQD2r37t0LYVxkwUg9ZHVgWPBXbuXzSX/uued6r7766jfR1jhpT2QgrDx27NgE6FmKvevll1/2NE5S7+DBg6Og5wyc3xSsiOx/4YUXIjW86tzooSkSDEmABEggYQIYenwvOvxtaHaiQ9MvI+3XMFSHUOY4PCMZpqtCXIzLfKRfj/BirV4b3hObieE+c4Wilhcqavwjz1kwSOZ7bkqgzKNBl3bo143VjlmvDWkl0K0UexXSR8AbLVflEfbBEL6Uj4enyXCM0qA5YmEiCZAACSRDAP8j7WIYCvmnnjeFbHEf5q8+ijmuP4aU41hd5sNgnC6BrpbVio6FvRO78f7da1HO96nmaNAUCYYkQAIkUEAC8NZugFGThSHvCaIGvKPnUe8HMBIPyftsQermU1a8NXwJZCrqmv9ixqcc+Wr/Mby6cBw66++x+ayeuxgNWm5GLEECJEACiRFYvnz5NAzRfRBG6gPYZ6JhGY6cYChwCsbgOOIvYn8WHtm/RfmlDaMNX4F4bBhaHA19RmP14jAZjoQHp4YW+xDvRV4HzuEszuc0FoKY/4bGVwMsRAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAKDgMD/D2WyCk5hENCOAAAAAElFTkSuQmCC); + background-size: 218px 188px; + display: inline-block; + } +} + +.tui-toolbar-icons.tui-heading { + background-position: -172px -48px; +} + +.tui-toolbar-icons.tui-heading:disabled { + background-position: -193px -48px; +} + +.tui-toolbar-icons.tui-bold { + background-position: -4px -4px; +} + +.tui-toolbar-icons.tui-bold:disabled { + background-position: -25px -4px; +} + +.tui-toolbar-icons.tui-italic { + background-position: -4px -48px; +} + +.tui-toolbar-icons.tui-italic:disabled { + background-position: -25px -48px; +} + +.tui-toolbar-icons.tui-color { + background-position: -172px -70px; +} + +.tui-toolbar-icons.tui-color:disabled { + background-position: -193px -70px; +} + +.tui-toolbar-icons.tui-strike { + background-position: -4px -26px; +} + +.tui-toolbar-icons.tui-strike:disabled { + background-position: -25px -26px; +} + +.tui-toolbar-icons.tui-hrline { + background-position: -46px -92px; +} + +.tui-toolbar-icons.tui-hrline:disabled { + background-position: -67px -92px; +} + +.tui-toolbar-icons.tui-quote { + background-position: -4px -114px; +} + +.tui-toolbar-icons.tui-quote:disabled { + background-position: -25px -114px; +} + +.tui-toolbar-icons.tui-ul { + background-position: -46px -4px; +} + +.tui-toolbar-icons.tui-ul:disabled { + background-position: -67px -4px; +} + +.tui-toolbar-icons.tui-ol { + background-position: -46px -26px; +} + +.tui-toolbar-icons.tui-ol:disabled { + background-position: -67px -26px; +} + +.tui-toolbar-icons.tui-task { + background-position: -130px -48px; +} + +.tui-toolbar-icons.tui-task:disabled { + background-position: -151px -48px; +} + +.tui-toolbar-icons.tui-indent { + background-position: -46px -48px; +} + +.tui-toolbar-icons.tui-indent:disabled { + background-position: -67px -48px; +} + +.tui-toolbar-icons.tui-outdent { + background-position: -46px -70px; +} + +.tui-toolbar-icons.tui-outdent:disabled { + background-position: -67px -70px; +} + +.tui-toolbar-icons.tui-table { + background-position: -88px -92px; +} + +.tui-toolbar-icons.tui-table:disabled { + background-position: -109px -92px; +} + +.tui-toolbar-icons.tui-image { + background-position: -130px -4px; +} + +.tui-toolbar-icons.tui-image:disabled { + background-position: -151px -4px; +} + +.tui-toolbar-icons.tui-link { + background-position: -130px -26px; +} + +.tui-toolbar-icons.tui-link:disabled { + background-position: -151px -26px; +} + +.tui-toolbar-icons.tui-code { + background-position: -130px -92px; +} + +.tui-toolbar-icons.tui-code:disabled { + background-position: -151px -92px; +} + +.tui-toolbar-icons.tui-codeblock { + background-position: -130px -70px; +} + +.tui-toolbar-icons.tui-codeblock:disabled { + background-position: -151px -70px; +} + +.tui-toolbar-icons.tui-more { + background-position: -172px -92px; +} + +.tui-toolbar-icons.tui-more:disabled { + background-position: -193px -92px; +} +.tui-colorpicker-svg-slider { + border: 1px solid #ebebeb; +} +.tui-colorpicker-vml-slider { + border: 1px solid #ebebeb; +} +.tui-colorpicker-svg-huebar { + border: 1px solid #ebebeb; +} + +.tui-editor-pseudo-clipboard { + position: fixed; + left: -1000px; + top: -1000px; + width: 100px; + height: 100px; +} + +.te-ww-block-overlay.code-block-header { + text-align: right; + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +.te-ww-block-overlay.code-block-header span { + font-size: 10px; + font-weight: 600; + padding: 0px 10px; + color: #333333; + cursor: default; +} + +.te-ww-block-overlay.code-block-header button { + margin: 8px; + font-size: 10px; + color: #333333; + background-color: #f9f9f9; + border: 1px solid #dddddd; + padding: 4px; + height: auto; +} + +.te-popup-code-block-languages { + position: fixed; + box-sizing: border-box; + width: 130px; +} + +.te-popup-code-block-languages .tui-popup-body { + max-height: 169px; + overflow: auto; + padding: 0px; +} + +.te-popup-code-block-languages button { + width: 100%; + background-color: #fff; + border: none; + outline: 0; + padding: 0px 10px 0px 10px; + font-size: 12px; + line-height: 24px; + text-align: left; + color: #777; +} + +.te-popup-code-block-languages button.active { + background-color: #f4f4f4; +} + +.tui-popup-code-block-editor .tui-popup-wrapper { + width: 70%; + height: 70%; + margin: auto; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; +} + +.te-input-language { + position: relative; + margin-left: 15px; + cursor: pointer; +} + +.te-input-language input { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: 10px; + padding: 3px 5px; + border: 1px solid #dddddd; + background-color: #f9f9f9; + box-sizing: border-box; + width: 130px; + outline: none; +} + +.te-input-language input::-ms-clear { + display: none; +} + +.te-input-language::after { + content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxMnB4IiBoZWlnaHQ9IjE0cHgiIHZpZXdCb3g9IjAgMCAxMiAxNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT42Q0NBRDk2QS0yMjYxLTRFNDAtOTk1RC1DRUUyQUREQUQ3NkQ8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbS10cmFuZ2xlLWQtc2lkZSIgZmlsbD0iIzU1NTU1NSI+ICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlJlY3RhbmdsZS03IiBwb2ludHM9IjIgNSAxMCA1IDYgMTAiPjwvcG9seWdvbj4gICAgICAgIDwvZz4gICAgPC9nPjwvc3ZnPg==); + position: absolute; + top: 1px; + right: 3px; +} + +.te-input-language.active::after { + content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxMnB4IiBoZWlnaHQ9IjE0cHgiIHZpZXdCb3g9IjAgMCAxMiAxNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT5BNEZDRkIzMy0zNjdBLTREMjAtOEEyNC1DQ0I2ODFBMDZDODg8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbS10cmFuZ2xlLXVwLXNpZGUiIGZpbGw9IiM1NTU1NTUiPiAgICAgICAgICAgIDxwb2x5Z29uIGlkPSJSZWN0YW5nbGUtNyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNi4wMDAwMDAsIDYuNTAwMDAwKSBzY2FsZSgxLCAtMSkgdHJhbnNsYXRlKC02LjAwMDAwMCwgLTYuNTAwMDAwKSAiIHBvaW50cz0iMiA0IDEwIDQgNiA5Ij48L3BvbHlnb24+ICAgICAgICA8L2c+ICAgIDwvZz48L3N2Zz4=); +} + +.tui-popup-code-block-editor button { + margin: -1px 3px; +} + +.tui-popup-code-block-editor .tui-popup-header-buttons { + height: 20px; +} + +.tui-popup-code-block-editor .popup-editor-toggle-preview::after { + content: 'Preview off'; + color: #777; + margin-right: 22px; +} + +.tui-popup-code-block-editor .popup-editor-toggle-preview.active::after { + content: 'Preview on'; + color: #4b96e6; +} + +.tui-popup-code-block-editor .popup-editor-toggle-scroll::after { + content: 'Scroll off'; + color: #777; + margin-right: 16px; +} + +.tui-popup-code-block-editor .popup-editor-toggle-scroll.active::after { + content: 'Scroll on'; + color: #4b96e6; +} + +.tui-popup-code-block-editor .popup-editor-toggle-fit { + width: 18px; + height: 18px; + margin-top: 4px; + margin-right: 14px; + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCAxOCAxOCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT40OUQ4RTYyMy1GRTAyLTQ1RUUtQkQ5Ri0xMjUyQjEzRTU1MkQ8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbnRlbnRzLWV4cGFuZCIgZmlsbD0iIzU1NTU1NSI+ICAgICAgICAgICAgPHBhdGggZD0iTTMsMyBMOSwzIEw5LDUgTDUsNSBMNSw5IEwzLDkgTDMsMyBaIE0xNSwxNSBMOSwxNSBMOSwxMyBMMTMsMTMgTDEzLDkgTDE1LDkgTDE1LDE1IFoiIGlkPSJDb21iaW5lZC1TaGFwZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS4wMDAwMDAsIDkuMDAwMDAwKSBzY2FsZSgtMSwgMSkgdHJhbnNsYXRlKC05LjAwMDAwMCwgLTkuMDAwMDAwKSAiPjwvcGF0aD4gICAgICAgICAgICA8cG9seWdvbiBpZD0iTGluZSIgZmlsbC1ydWxlPSJub256ZXJvIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMS41MDAwMDAsIDYuNTAwMDAwKSBzY2FsZSgtMSwgMSkgdHJhbnNsYXRlKC0xMS41MDAwMDAsIC02LjUwMDAwMCkgIiBwb2ludHM9IjkuMDg1Nzg2NDQgNS41IDEyLjUgOC45MTQyMTM1NiAxMy45MTQyMTM2IDcuNSAxMC41IDQuMDg1Nzg2NDQiPjwvcG9seWdvbj4gICAgICAgICAgICA8cG9seWdvbiBpZD0iTGluZS1Db3B5IiBmaWxsLXJ1bGU9Im5vbnplcm8iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDYuNTAwMDAwLCAxMS41MDAwMDApIHNjYWxlKC0xLCAxKSB0cmFuc2xhdGUoLTYuNTAwMDAwLCAtMTEuNTAwMDAwKSAiIHBvaW50cz0iNC4wODU3ODY0NCAxMC41IDcuNSAxMy45MTQyMTM2IDguOTE0MjEzNTYgMTIuNSA1LjUgOS4wODU3ODY0NCI+PC9wb2x5Z29uPiAgICAgICAgPC9nPiAgICA8L2c+PC9zdmc+); +} + +.tui-popup-code-block-editor .popup-editor-toggle-fit.active { + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCAxOCAxOCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT4wN0Q1MjlCRi1GNTIzLTREN0EtQTlGNi05NTUzNTU5RDNEMUE8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbnRlbnRzLXJlZHVjZSIgZmlsbD0iIzU1NTU1NSI+ICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgtMzIiIGZpbGwtcnVsZT0ibm9uemVybyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNS41MDAwMDAsIDEyLjUwMDAwMCkgc2NhbGUoLTEsIDEpIHRyYW5zbGF0ZSgtNS41MDAwMDAsIC0xMi41MDAwMDApICIgcG9pbnRzPSIzLjA4NTc4NjQ0IDExLjUgNi41IDE0LjkxNDIxMzYgNy45MTQyMTM1NiAxMy41IDQuNSAxMC4wODU3ODY0Ij48L3BvbHlnb24+ICAgICAgICAgICAgPHBhdGggZD0iTTksOSBMMTUsOSBMMTUsMTEgTDExLDExIEwxMSwxNSBMOSwxNSBMOSw5IFogTTksOSBMMyw5IEwzLDcgTDcsNyBMNywzIEw5LDMgTDksOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMDAwMDAwLCA5LjAwMDAwMCkgc2NhbGUoLTEsIDEpIHRyYW5zbGF0ZSgtOS4wMDAwMDAsIC05LjAwMDAwMCkgIj48L3BhdGg+ICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgtMzMiIGZpbGwtcnVsZT0ibm9uemVybyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTIuNTAwMDAwLCA1LjUwMDAwMCkgc2NhbGUoLTEsIDEpIHRyYW5zbGF0ZSgtMTIuNTAwMDAwLCAtNS41MDAwMDApICIgcG9pbnRzPSIxNC45MTQyMTM2IDYuNSAxMS41IDMuMDg1Nzg2NDQgMTAuMDg1Nzg2NCA0LjUgMTMuNSA3LjkxNDIxMzU2Ij48L3BvbHlnb24+ICAgICAgICA8L2c+ICAgIDwvZz48L3N2Zz4=); +} + +.tui-popup-code-block-editor .tui-popup-close-button { + margin-top: 6px; +} + +.tui-popup-code-block-editor .tui-popup-body { + z-index: -1; + padding: 0px; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex: 1; + flex: 1; +} + +.tui-popup-code-block-editor .popup-editor-body { + position: relative; + -ms-flex: 1; + flex: 1; + border-bottom: 1px solid #cacaca; +} + +.tui-popup-code-block-editor .te-button-section { + padding: 15px; +} + +.tui-popup-code-block-editor .te-button-section button { + float: left; +} + +.tui-popup-code-block-editor .tui-editor-contents pre { + margin: 0px; + background-color: transparent; +} + +.tui-popup-code-block-editor .CodeMirror { + height: auto; +} + +.tui-popup-code-block-editor .CodeMirror-line { + font-family: Consolas, Courier, 'Lucida Grande', '나눔바른고딕', 'Nanum Barun Gothic', '맑은고딕', + 'Malgun Gothic', sans-serif; + font-size: 13px; + line-height: 160%; + letter-spacing: -0.3px; +} + +.tui-popup-code-block-editor .popup-editor-editor-wrapper { + min-height: 100%; +} + +.tui-split-scroll-wrapper { + position: relative; +} + +.tui-split-scroll { + position: absolute; +} + +.tui-split-scroll, +.tui-split-scroll-wrapper { + width: 100%; + height: 100%; +} + +.tui-split-scroll .tui-split-content-left, +.tui-split-scroll .tui-split-content-right { + position: absolute; + top: 0px; + width: 50%; + box-sizing: border-box; +} + +.tui-split-scroll .tui-split-content-left { + left: 0px; +} + +.tui-split-scroll .tui-split-content-right { + left: 50%; +} + +.tui-split-scroll .tui-splitter { + position: absolute; + left: 50%; + top: 0; + height: 100%; + width: 1px; + border-left: 1px solid #cacaca; +} + +.tui-split-scroll .tui-split-scroll-content { + width: 100%; + height: 100%; + overflow: hidden; + position: relative; +} + +.tui-split-scroll .tui-split-content-left, +.tui-split-scroll .tui-split-content-right { + height: 100%; + overflow-x: hidden; + overflow-y: auto; +} + +.tui-split-scroll button.tui-scrollsync { + top: 10px; + opacity: 0.2; +} + +.tui-split-scroll button.tui-scrollsync::after { + content: 'scroll off'; +} + +.tui-split-scroll.scroll-sync button.tui-scrollsync { + opacity: 0.5; +} + +.tui-split-scroll.scroll-sync .tui-split-content-left, +.tui-split-scroll.scroll-sync .tui-split-content-right { + height: auto; + overflow: initial; +} + +.tui-split-scroll.scroll-sync button.tui-scrollsync::after { + content: 'scroll on'; +} + +.tui-split-scroll.scroll-sync .tui-split-scroll-content { + overflow-y: auto; +} + +.tui-split-scroll.single-content .tui-splitter { + display: none; +} + +.tui-split-scroll.single-content .tui-split-content-left { + width: 100%; +} + +.tui-split-scroll.single-content .tui-split-content-right { + display: none; +} + +.tui-split-scroll.single-content button.tui-scrollsync { + display: none; +} + +@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { + /* IE10+ */ + .tui-split-scroll-wrapper .tui-splitter { + left: calc(50% - 9px); + } +} + +@supports (-ms-accelerator: true) { + /* IE Edge 12+ CSS styles go here */ + .tui-split-scroll-wrapper .tui-splitter { + left: calc(50% - 9px); + } +} + +@media screen and (max-width: 480px) { + .tui-popup-wrapper { + max-width: 300px; + } + + .tui-editor-popup { + margin-left: -150px; + } + + .te-dropdown-toolbar { + max-width: none; + } +} + +.tui-editor-contents .te-preview-highlight { + position: relative; + z-index: 0; +} + +.tui-editor-contents .te-preview-highlight::after { + content: ''; + background-color: rgba(255, 245, 131, 0.5); + border-radius: 4px; + z-index: -1; + position: absolute; + top: -4px; + right: -4px; + left: -4px; + bottom: -4px; +} + +.tui-editor-contents h1.te-preview-highlight::after, +.tui-editor-contents h2.te-preview-highlight::after { + bottom: 0; +} + +.tui-editor-contents td.te-preview-highlight::after, +.tui-editor-contents th.te-preview-highlight::after { + display: none; +} + +.tui-editor-contents th.te-preview-highlight, +.tui-editor-contents td.te-preview-highlight { + background-color: rgba(255, 245, 131, 0.5); +} + +.tui-editor-contents th.te-preview-highlight { + color: #222; +} + +.te-md-container .CodeMirror { + font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', 'Arial', '나눔바른고딕', + 'Nanum Barun Gothic', '맑은고딕', 'Malgun Gothic', sans-serif; + color: #222; +} + +.tui-md-heading1 { + font-size: 24px; +} + +.tui-md-heading2 { + font-size: 22px; +} + +.tui-md-heading3 { + font-size: 20px; +} + +.tui-md-heading4 { + font-size: 18px; +} + +.tui-md-heading5 { + font-size: 16px; +} + +.tui-md-heading6 { + font-size: 14px; +} + +.tui-md-heading.tui-md-delimiter.setext { + line-height: 15px; +} + +.tui-md-strong, +.tui-md-heading, +.tui-md-list-item.tui-md-list-item-bullet, +.tui-md-list-item.tui-md-meta { + font-weight: bold; +} + +.tui-md-emph { + font-style: italic; +} + +.tui-md-strike { + text-decoration: line-through; +} + +.tui-md-strike.tui-md-delimiter { + text-decoration: none; +} + +.tui-md-delimiter, +.tui-md-thematic-break, +.tui-md-link, +.tui-md-table, +.tui-md-block-quote { + color: #ccc; +} + +.tui-md-code-block.tui-md-meta, +.tui-md-code.tui-md-delimiter { + color: #aaa; +} + +.tui-md-meta, +.tui-md-html, +.tui-md-link.tui-md-link-url.tui-md-marked-text { + color: #999; +} + +.tui-md-block-quote.tui-md-marked-text, +.tui-md-list-item.tui-md-meta { + color: #555; +} + +.tui-md-table.tui-md-marked-text { + color: #222; +} + +.tui-md-link.tui-md-link-desc.tui-md-marked-text, +.tui-md-list-item-odd.tui-md-list-item-bullet { + color: #4b96e6; +} + +.tui-md-list-item-even.tui-md-list-item-bullet { + color: #cb4848; +} + +.tui-md-code.tui-md-marked-text { + color: #c1798b; +} + +.tui-md-code { + background-color: rgba(243, 229, 233, 0.5); + padding: 2px 0; + letter-spacing: -0.3px; +} + +.tui-md-code.tui-md-delimiter.start { + padding-left: 2px; + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; +} + +.tui-md-code.tui-md-delimiter.end { + padding-right: 2px; + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; +} + +.tui-md-code-block.CodeMirror-linebackground { + left: 20px; + right: 20px; + background-color: #f5f7f8; +} + +.tui-md-code-block.CodeMirror-linebackground.start { + top: 2px; +} + +.tui-md-code-block.CodeMirror-linebackground.end { + bottom: 2px; +} + +.tui-md-code, +.tui-md-code-block { + font-family: Consolas, Courier, 'Lucida Grande', '나눔바른고딕', 'Nanum Barun Gothic', '맑은고딕', + 'Malgun Gothic', sans-serif; +} + diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-viewer-old.css b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-viewer-old.css new file mode 100644 index 0000000000..ed8facad3c --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-viewer-old.css @@ -0,0 +1,280 @@ +/*! + * @toast-ui/editor + * @version 2.5.1 | Tue Nov 24 2020 + * @author NHN FE Development Lab + * @license MIT + */ +@charset "utf-8"; +.CodeMirror { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +.tui-editor-contents *:not(table) { + line-height: 160%; + box-sizing: content-box; +} + +.tui-editor-contents i, +.tui-editor-contents cite, +.tui-editor-contents em, +.tui-editor-contents var, +.tui-editor-contents address, +.tui-editor-contents dfn { + font-style: italic; +} + +.tui-editor-contents strong { + font-weight: bold; +} + +.tui-editor-contents p { + margin: 10px 0; + color: #555; +} + +.tui-editor-contents > h1:first-of-type, +.tui-editor-contents > div > div:first-of-type h1 { + margin-top: 14px; +} + +.tui-editor-contents h1, +.tui-editor-contents h2, +.tui-editor-contents h3, +.tui-editor-contents h5 { + font-weight: bold; +} + +.tui-editor-contents h1 { + font-size: 1.6rem; + line-height: 28px; + border-bottom: 3px double #999; + margin: 52px 0 15px 0; + padding-bottom: 7px; + color: #000; +} + +.tui-editor-contents h2 { + font-size: 1.3rem; + line-height: 23px; + border-bottom: 1px solid #dbdbdb; + margin: 30px 0 13px 0; + padding-bottom: 7px; + color: #333; +} + +.tui-editor-contents h3, +.tui-editor-contents h4 { + font-size: 1.2rem; + line-height: 18px; + margin: 20px 0 2px; + color: #333; +} + +.tui-editor-contents h5, +.tui-editor-contents h6 { + font-size: 1rem; + line-height: 17px; + margin: 10px 0 -4px; + color: #333; +} + +.tui-editor-contents blockquote { + margin: 15px 0; +} + +.tui-editor-contents blockquote { + border-left: 4px solid #dddddd; + padding: 0 15px; + color: #777777; +} + +.tui-editor-contents blockquote > :first-child { + margin-top: 0; +} + +.tui-editor-contents blockquote > :last-child { + margin-bottom: 0; +} + +.tui-editor-contents pre, +.tui-editor-contents code { + font-family: Consolas, Courier, 'Lucida Grande', '나눔바른고딕', 'Nanum Barun Gothic', '맑은고딕', + 'Malgun Gothic', sans-serif; + border: 0; + border-radius: 0; +} + +.tui-editor-contents pre { + margin: 2px 0 8px; + padding: 18px; + background-color: #f5f7f8; +} + +.tui-editor-contents code { + color: #c1788b; + padding: 4px 4px 2px 0; + letter-spacing: -0.3px; +} + +.tui-editor-contents pre code { + padding: 0; + color: inherit; + white-space: pre-wrap; + background-color: transparent; +} + +.tui-editor-contents pre.addon { + border: 1px solid #e8ebed; + background-color: #fff; +} + +.tui-editor-contents img { + margin: 4px 0 10px; + box-sizing: border-box; + vertical-align: top; + max-width: 100%; +} + +.tui-editor-contents table { + margin: 2px 0 14px; + color: #555; + width: auto; + border-collapse: collapse; + box-sizing: border-box; +} + +.tui-editor-contents table th, +.tui-editor-contents table td { + height: 32px; + padding: 5px 14px 5px 12px; +} + +.tui-editor-contents table td { + border: 1px solid #eaeaea; +} + +.tui-editor-contents table th { + border: 1px solid #72777b; + border-top: 0; + background-color: #7b8184; + font-weight: 300; + color: #fff; + padding-top: 6px; +} + +.tui-editor-contents ul, +.tui-editor-contents menu, +.tui-editor-contents ol, +.tui-editor-contents dir { + display: block; + list-style-type: disc; + padding-left: 17px; + margin: 6px 0 10px; + color: #555; +} + +.tui-editor-contents ol { + list-style-type: decimal; +} + +.tui-editor-contents ul ul, +.tui-editor-contents ul ol, +.tui-editor-contents ol ol, +.tui-editor-contents ol ul { + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +.tui-editor-contents ul li, +.tui-editor-contents ol li { + position: relative; +} + +.tui-editor-contents ul p, +ol p { + margin: 0; +} + +.tui-editor-contents ul li.task-list-item:before, +.tui-editor-contents ol li.task-list-item:before, +.tui-editor-contents pre ul li:before { + content: ''; +} + +.tui-editor-contents hr { + border-top: 1px solid #eee; + margin: 16px 0; +} + +.tui-editor-contents a { + text-decoration: underline; + color: #5286bc; +} + +.tui-editor-contents a:hover { + color: #007cff; +} + +.tui-editor-contents a.image-link { + position: relative; +} + +.tui-editor-contents a.image-link::before { + content: ''; + position: absolute; + margin: 0; + width: 20px; + height: 20px; + top: 2px; + right: 2px; + background-repeat: no-repeat; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAFKADAAQAAAABAAAAFAAAAACy3fD9AAAA/0lEQVQ4Ee2UIY6FQAyG/91wAQQJDg8SSwI3QIFAcQHuwFHQoOAEEFAELB6H4wIku+9vQgIP9zLyVbTTTufLtJ3MzzRNf1AoGlmu6ypBzvOMXyWkC+QLvDTjw6VM+Xr2OA6UZYmu67Dvu2zleX6zuq7D933EcQxNuyPu3usYYXVdw/M8mKYpIMMwxEZRJHbbNsmhkySJxE71APJmhGVZhnVdURQFlmU585GmKSzLEp+570Dlz+ZxQ/aGJVNYsm3bCIJA/LZtMY4jmqbBMAwIw1DiV/UAstEUltP3vawdxxFbVZVYDoWwM1eCp+LnoErIUt7DL/Ac1edWng1/WlXyD380myY5A34sAAAAAElFTkSuQmCC'); + cursor: pointer; +} + +.tui-editor-contents { + font-size: 13px; + margin: 0; + padding: 0; +} + +.tui-editor-contents .task-list-item { + border: 0; + list-style: none; + padding-left: 22px; + margin-left: -22px; + min-height: 20px; +} + +.tui-editor-contents .task-list-item:before { + background-repeat: no-repeat; + background-size: 16px 16px; + background-position: center; + content: ''; + height: 18px; + width: 18px; + position: absolute; + left: 0; + top: 1px; + cursor: pointer; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAADdJREFUKBVjvHv37n8GMgALSI+SkhJJWu/du8fARJIOJMWjGpECA505GjjoIYLEB6dVUNojFQAA/1MJUFWet/4AAAAASUVORK5CYII='); +} + +.tui-editor-contents .task-list-item.checked:before { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAMpJREFUKBVjjJ/64D8DGYCJDD1gLbTVyM3OxJDiJMzAxcYIdyALnIWDAdJU7i/OICfCxsDMxMgwc88bwk5F1vTs/W+GFUffwY2H+1FBlI2hLliCQYCbGSyJrqlzwwuGj9//YWoMtRBgUBJnZ6gMEGeQFWaFOw9kE7omkG5GWDyCPF7mJ86gIMbO8P//fwZGRkYGXJpAGuFO/fbrP0PXppcMD179JKgJRSOIA9N8/NZXrM4DqYEBjOgAaYYFOUwRNhruVGyS+MTI1ggAx8NTGcUtFVQAAAAASUVORK5CYII='); +} + +.tui-editor-contents .task-list-item input[type='checkbox'], +.tui-editor-contents .task-list-item .task-list-item-checkbox { + margin-left: -17px; + margin-right: 3.8px; + margin-top: 3px; +} + +.tui-editor-contents-placeholder:before { + content: attr(data-placeholder); + color: grey; + line-height: 160%; + position: absolute; +} + diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-viewer.css b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-viewer.css new file mode 100644 index 0000000000..2766d2969d --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-viewer.css @@ -0,0 +1,377 @@ +/*! + * @toast-ui/editor + * @version 2.5.1 | Tue Nov 24 2020 + * @author NHN FE Development Lab + * @license MIT + */ +@charset "utf-8"; +.tui-editor-contents { + margin: 0; + padding: 0; + font-size: 13px; + font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', 'Arial', '나눔바른고딕', + 'Nanum Barun Gothic', '맑은고딕', 'Malgun Gothic', sans-serif; +} + +.tui-editor-contents *:not(table) { + line-height: 160%; + box-sizing: content-box; +} + +.tui-editor-contents i, +.tui-editor-contents cite, +.tui-editor-contents em, +.tui-editor-contents var, +.tui-editor-contents address, +.tui-editor-contents dfn { + font-style: italic; +} + +.tui-editor-contents strong { + font-weight: bold; +} + +.tui-editor-contents p { + margin: 10px 0; + color: #222; +} + +.tui-editor-contents > h1:first-of-type, +.tui-editor-contents > div > div:first-of-type h1 { + margin-top: 14px; +} + +.tui-editor-contents h1, +.tui-editor-contents h2, +.tui-editor-contents h3, +.tui-editor-contents h4, +.tui-editor-contents h5, +.tui-editor-contents h6 { + font-weight: bold; + color: #222; +} + +.tui-editor-contents h1 { + font-size: 24px; + line-height: 28px; + border-bottom: 3px double #999; + margin: 52px 0 15px 0; + padding-bottom: 7px; +} + +.tui-editor-contents h2 { + font-size: 22px; + line-height: 23px; + border-bottom: 1px solid #dbdbdb; + margin: 20px 0 13px 0; + padding-bottom: 7px; +} + +.tui-editor-contents h3 { + font-size: 20px; + margin: 18px 0 2px; +} + +.tui-editor-contents h4 { + font-size: 18px; + margin: 10px 0 2px; +} + +.tui-editor-contents h3, +.tui-editor-contents h4 { + line-height: 18px; +} + +.tui-editor-contents h5 { + font-size: 16px; +} + +.tui-editor-contents h6 { + font-size: 14px; +} + +.tui-editor-contents h5, +.tui-editor-contents h6 { + line-height: 17px; + margin: 9px 0 -4px; +} + +.tui-editor-contents del { + color: #999; +} + +.tui-editor-contents blockquote { + margin: 14px 0; + border-left: 4px solid #e5e5e5; + padding: 0 16px; + color: #999; +} + +.tui-editor-contents blockquote p, +.tui-editor-contents blockquote ul, +.tui-editor-contents blockquote ol { + color: #999; +} + +.tui-editor-contents blockquote > :first-child { + margin-top: 0; +} + +.tui-editor-contents blockquote > :last-child { + margin-bottom: 0; +} + +.tui-editor-contents pre, +.tui-editor-contents code { + font-family: Consolas, Courier, 'Apple SD 산돌고딕 Neo', -apple-system, 'Lucida Grande', + 'Apple SD Gothic Neo', '맑은 고딕', 'Malgun Gothic', 'Segoe UI', '돋움', dotum, sans-serif; + border: 0; + border-radius: 0; +} + +.tui-editor-contents pre { + margin: 2px 0 8px; + padding: 18px; + background-color: #f5f7f8; +} + +.tui-editor-contents code { + color: #c1798b; + background-color: #f9f2f4; + padding: 2px 3px; + letter-spacing: -0.3px; + border-radius: 2px; +} + +.tui-editor-contents pre code { + padding: 0; + color: inherit; + white-space: pre-wrap; + background-color: transparent; +} + +.tui-editor-contents pre.addon { + border: 1px solid #e8ebed; + background-color: #fff; +} + +.tui-editor-contents img { + margin: 4px 0 10px; + box-sizing: border-box; + vertical-align: top; + max-width: 100%; +} + +.tui-editor-contents table { + border: 1px solid rgba(0, 0, 0, 0.1); + margin: 12px 0 14px; + color: #222; + width: auto; + border-collapse: collapse; + box-sizing: border-box; +} + +.tui-editor-contents table th, +.tui-editor-contents table td { + border: 1px solid rgba(0, 0, 0, 0.1); + padding: 5px 14px 5px 12px; + height: 32px; +} + +.tui-editor-contents table th { + background-color: #555; + font-weight: 300; + color: #fff; + padding-top: 6px; +} + +.tui-editor-contents ul, +.tui-editor-contents menu, +.tui-editor-contents ol, +.tui-editor-contents dir { + display: block; + list-style-type: none; + padding-left: 24px; + margin: 6px 0 10px; + color: #222; +} + +.tui-editor-contents ol { + list-style-type: none; + counter-reset: li; +} + +.tui-editor-contents ol > li { + counter-increment: li; +} + +.tui-editor-contents ul > li::before, +.tui-editor-contents ol > li::before { + display: inline-block; + position: absolute; +} + +.tui-editor-contents ul > li::before { + content: ''; + margin-top: 6px; + margin-left: -17px; + width: 5px; + height: 5px; + border-radius: 50%; + background-color: #ccc; +} + +.tui-editor-contents ol > li::before { + content: '.' counter(li); + margin-left: -28px; + width: 24px; + text-align: right; + direction: rtl; + color: #aaa; +} + +.tui-editor-contents ul ul, +.tui-editor-contents ul ol, +.tui-editor-contents ol ol, +.tui-editor-contents ol ul { + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +.tui-editor-contents ul li, +.tui-editor-contents ol li { + position: relative; +} + +.tui-editor-contents ul p, +.tui-editor-contents ol p { + margin: 0; +} + +.tui-editor-contents ul li.task-list-item::before, +.tui-editor-contents ol li.task-list-item::before, +.tui-editor-contents pre ul li::before { + content: ''; +} + +.tui-editor-contents th ol, +.tui-editor-contents th ul { + color: #fff; +} + +.tui-editor-contents hr { + border-top: 1px solid #eee; + margin: 16px 0; +} + +.tui-editor-contents a { + text-decoration: underline; + color: #4b96e6; +} + +.tui-editor-contents a:hover { + color: #1f70de; +} + +.tui-editor-contents a.image-link { + position: relative; +} + +.tui-editor-contents a.image-link::before { + content: ''; + position: absolute; + margin: 0; + width: 20px; + height: 20px; + top: 2px; + right: 2px; + background-repeat: no-repeat; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAFKADAAQAAAABAAAAFAAAAACy3fD9AAAA/0lEQVQ4Ee2UIY6FQAyG/91wAQQJDg8SSwI3QIFAcQHuwFHQoOAEEFAELB6H4wIku+9vQgIP9zLyVbTTTufLtJ3MzzRNf1AoGlmu6ypBzvOMXyWkC+QLvDTjw6VM+Xr2OA6UZYmu67Dvu2zleX6zuq7D933EcQxNuyPu3usYYXVdw/M8mKYpIMMwxEZRJHbbNsmhkySJxE71APJmhGVZhnVdURQFlmU585GmKSzLEp+570Dlz+ZxQ/aGJVNYsm3bCIJA/LZtMY4jmqbBMAwIw1DiV/UAstEUltP3vawdxxFbVZVYDoWwM1eCp+LnoErIUt7DL/Ac1edWng1/WlXyD380myY5A34sAAAAAElFTkSuQmCC'); + cursor: pointer; +} + +.tui-editor-contents .task-list-item { + border: 0; + list-style: none; + padding-left: 24px; + margin-left: -24px; +} + +.tui-editor-contents .task-list-item::before { + background-repeat: no-repeat; + background-size: 18px 18px; + background-position: center; + content: ''; + margin-left: 0; + margin-top: 0; + border-radius: 0; + height: 18px; + width: 18px; + position: absolute; + left: 0; + top: 1px; + cursor: pointer; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAEqADAAQAAAABAAAAEgAAAACaqbJVAAAAQklEQVQ4EWM8c+bMfwYqABaQGcbGxhQZdfbsWQYmikxA0jxqEFJg4GCOhhGOgEESHg0jpMDAwRx8YQQuj0DlCaUAAEdBCPJ7TaEPAAAAAElFTkSuQmCC'); +} + +.tui-editor-contents .task-list-item.checked::before { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAEqADAAQAAAABAAAAEgAAAACaqbJVAAAA1ElEQVQ4EWP0nvbsPwMVABMVzAAbMWoQIiT5OJgYvLS5EAJQFguGCB4BkCHt/kIM8kKsYFXbrn6DqyY6sJENefjuN8ORuz/ghoAYWA0COR2kEQbQDanc+I7h049/MGkwjVANFQYZkmXHD/YCyABiDAFpxQgjkJO9dbjA4QAKDxAAhQnIO9hcAlYAJDBcBHIySANII8gAYgwBGYZhEEgQZFjVJohhhFwCUg8CjPgyLT8nE8N/YJZGD1iIVlQSI4yQpT9+R40ZZDl0NlavoSsihj/4DAIAR+hZHUj727YAAAAASUVORK5CYII='); +} + +.tui-editor-contents .task-list-item input[type='checkbox'], +.tui-editor-contents .task-list-item .task-list-item-checkbox { + margin-left: -17px; + margin-right: 3.8px; + margin-top: 3px; +} + +.tui-editor-contents-placeholder::before { + content: attr(data-placeholder); + color: grey; + line-height: 160%; + position: absolute; +} + +.te-preview .tui-editor-contents h1 { + min-height: 28px; +} + +.te-preview .tui-editor-contents h2 { + min-height: 23px; +} + +.te-preview .tui-editor-contents blockquote { + min-height: 20px; +} + +.te-preview .tui-editor-contents li { + min-height: 22px; +} + +@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { + /* IE10+11 */ + .te-ww-container .tui-editor-contents li { + vertical-align: middle; + } + + .te-ww-container .tui-editor-contents ul > li::before, + .te-ww-container .tui-editor-contents ol > li::before, + .te-ww-container .tui-editor-contents .task-list-item:before { + position: static; + vertical-align: middle; + } + + .te-ww-container .tui-editor-contents ul > li::before { + margin-top: -3px; + margin-right: 12px; + } + + .te-ww-container .tui-editor-contents ol > li::before { + margin-right: 6px; + } + + .te-ww-container .tui-editor-contents .task-list-item { + padding-left: 2px; + } +} + diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-viewer.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-viewer.js new file mode 100644 index 0000000000..7a89d894fa --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor-viewer.js @@ -0,0 +1,6878 @@ +/*! + * @toast-ui/editor + * @version 2.5.1 | Tue Nov 24 2020 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["Editor"] = factory(); + else + root["toastui"] = root["toastui"] || {}, root["toastui"]["Editor"] = factory(); +})(window, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 60); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); +/* harmony import */ var tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9); +/* harmony import */ var tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var tui_code_snippet_domUtil_css__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4); +/* harmony import */ var tui_code_snippet_domUtil_css__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_css__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5); +/* harmony import */ var tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_4__); +/* harmony import */ var tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6); +/* harmony import */ var tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_5__); +/* harmony import */ var tui_code_snippet_domUtil_hasClass__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(16); +/* harmony import */ var tui_code_snippet_domUtil_hasClass__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_hasClass__WEBPACK_IMPORTED_MODULE_6__); +/* harmony import */ var tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(13); +/* harmony import */ var tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7__); +/** + * @fileoverview DOM Utils + * @author NHN FE Development Lab + */ + + + + + + + + +var FIND_ZWB = /\u200B/g; +var _window = window, + getComputedStyle = _window.getComputedStyle; +/** + * Check if node is text node + * @param {Node} node node to check + * @returns {boolean} result + * @ignore + */ + +var isTextNode = function isTextNode(node) { + return node && node.nodeType === Node.TEXT_NODE; +}; +/** + * Check if node is element node + * @param {Node} node node to check + * @returns {boolean} result + * @ignore + */ + + +var isElemNode = function isElemNode(node) { + return node && node.nodeType === Node.ELEMENT_NODE; +}; +/** + * Check that the node is block node + * @param {Node} node node + * @returns {boolean} + * @ignore + */ + + +var isBlockNode = function isBlockNode(node) { + return /^(ADDRESS|ARTICLE|ASIDE|BLOCKQUOTE|DETAILS|DIALOG|DD|DIV|DL|DT|FIELDSET|FIGCAPTION|FIGURE|FOOTER|FORM|H[\d]|HEADER|HGROUP|HR|LI|MAIN|NAV|OL|P|PRE|SECTION|UL)$/gi.test(this.getNodeName(node)); +}; +/** + * Get node name of node + * @param {Node} node node + * @returns {string} node name + * @ignore + */ + + +var getNodeName = function getNodeName(node) { + if (isElemNode(node)) { + return node.tagName; + } + + return 'TEXT'; +}; +/** + * Get node offset length of node(for Range API) + * @param {Node} node node + * @returns {number} length + * @ignore + */ + + +var getTextLength = function getTextLength(node) { + var len; + + if (isElemNode(node)) { + len = node.textContent.replace(FIND_ZWB, '').length; + } else if (isTextNode(node)) { + len = node.nodeValue.replace(FIND_ZWB, '').length; + } + + return len; +}; +/** + * Get node offset length of node(for Range API) + * @param {Node} node node + * @returns {number} length + * @ignore + */ + + +var getOffsetLength = function getOffsetLength(node) { + var len; + + if (isElemNode(node)) { + len = node.childNodes.length; + } else if (isTextNode(node)) { + len = node.nodeValue.replace(FIND_ZWB, '').length; + } + + return len; +}; +/** + * get node offset between parent's childnodes + * @param {Node} node node + * @returns {number} offset(index) + * @ignore + */ + + +var getNodeOffsetOfParent = function getNodeOffsetOfParent(node) { + var childNodesOfParent = node.parentNode.childNodes; + var i, t, found; + + for (i = 0, t = childNodesOfParent.length; i < t; i += 1) { + if (childNodesOfParent[i] === node) { + found = i; + break; + } + } + + return found; +}; +/** + * get child node by offset + * @param {Node} node node + * @param {number} index offset index + * @returns {Node} foudned node + * @ignore + */ + + +var getChildNodeByOffset = function getChildNodeByOffset(node, index) { + var currentNode; + + if (isTextNode(node)) { + currentNode = node; + } else if (node.childNodes.length && index >= 0) { + currentNode = node.childNodes[index]; + } + + return currentNode; +}; +/** + * find next node from passed node + * @param {strong} direction previous or next + * @param {Node} node node + * @param {string} untilNodeName parent node name to limit + * @returns {Node} founded node + * @ignore + */ + + +var getNodeWithDirectionUntil = function getNodeWithDirectionUntil(direction, node, untilNodeName) { + var directionKey = direction + "Sibling"; + var nodeName, foundedNode; + + while (node && !node[directionKey]) { + nodeName = getNodeName(node.parentNode); + + if (nodeName === untilNodeName || nodeName === 'BODY') { + break; + } + + node = node.parentNode; + } + + if (node[directionKey]) { + foundedNode = node[directionKey]; + } + + return foundedNode; +}; +/** + * get prev node of childnode pointed with index + * @param {Node} node node + * @param {number} index offset index + * @param {string} untilNodeName parent node name to limit + * @returns {Node} founded node + * @ignore + */ + + +var getPrevOffsetNodeUntil = function getPrevOffsetNodeUntil(node, index, untilNodeName) { + var prevNode; + + if (index > 0) { + prevNode = getChildNodeByOffset(node, index - 1); + } else { + prevNode = getNodeWithDirectionUntil('previous', node, untilNodeName); + } + + return prevNode; +}; + +var getParentUntilBy = function getParentUntilBy(node, matchCondition, stopCondition) { + while (node.parentNode && !matchCondition(node.parentNode)) { + node = node.parentNode; + + if (stopCondition && stopCondition(node)) { + break; + } + } + + if (matchCondition(node.parentNode)) { + return node; + } + + return null; +}; +/** + * get parent node until paseed node name + * @param {Node} node node + * @param {string|HTMLNode} untilNode node name or node to limit + * @returns {Node} founded node + * @ignore + */ + + +var getParentUntil = function getParentUntil(node, untilNode) { + var foundedNode; + + if (tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default()(untilNode)) { + foundedNode = getParentUntilBy(node, function (targetNode) { + return untilNode === getNodeName(targetNode); + }); + } else { + foundedNode = getParentUntilBy(node, function (targetNode) { + return untilNode === targetNode; + }); + } + + return foundedNode; +}; +/** + * get node on the given direction under given parent + * @param {strong} direction previous or next + * @param {Node} node node + * @param {string|Node} underNode parent node name to limit + * @returns {Node} founded node + * @ignore + */ + + +var getNodeWithDirectionUnderParent = function getNodeWithDirectionUnderParent(direction, node, underNode) { + var directionKey = direction + "Sibling"; + var foundedNode; + node = getParentUntil(node, underNode); + + if (node && node[directionKey]) { + foundedNode = node[directionKey]; + } + + return foundedNode; +}; +/** + * get top previous top level node under given node + * @param {Node} node node + * @param {Node} underNode underNode + * @returns {Node} founded node + * @ignore + */ + + +var getTopPrevNodeUnder = function getTopPrevNodeUnder(node, underNode) { + return getNodeWithDirectionUnderParent('previous', node, underNode); +}; +/** + * get next top level block node + * @param {Node} node node + * @param {Node} underNode underNode + * @returns {Node} founded node + * @ignore + */ + + +var getTopNextNodeUnder = function getTopNextNodeUnder(node, underNode) { + return getNodeWithDirectionUnderParent('next', node, underNode); +}; +/** + * Get parent element the body element + * @param {Node} node Node for start searching + * @returns {Node} + * @ignore + */ + + +var getTopBlockNode = function getTopBlockNode(node) { + return getParentUntil(node, 'BODY'); +}; +/** + * Get previous text node + * @param {Node} node Node for start searching + * @returns {Node} + * @ignore + */ + + +var getPrevTextNode = function getPrevTextNode(node) { + node = node.previousSibling || node.parentNode; + + while (!isTextNode(node) && getNodeName(node) !== 'BODY') { + if (node.previousSibling) { + node = node.previousSibling; + + while (node.lastChild) { + node = node.lastChild; + } + } else { + node = node.parentNode; + } + } + + if (getNodeName(node) === 'BODY') { + node = null; + } + + return node; +}; +/** + * test whether root contains the given node + * @param {HTMLNode|string} root - root node + * @param {HTMLNode} found - node to test + * @returns {Boolean} true if root contains node + * @ignore + */ + + +var containsNode = function containsNode(root, node) { + var walker = document.createTreeWalker(root, 4, null, false); + var found = root === node; + + while (!found && walker.nextNode()) { + found = walker.currentNode === node; + } + + return found; +}; +/** + * find node by offset + * @param {HTMLElement} root Root element + * @param {Array.} offsetList offset list + * @param {function} textNodeFilter Text node filter + * @returns {Array} + * @ignore + */ + + +var findOffsetNode = function findOffsetNode(root, offsetList, textNodeFilter) { + var result = []; + var text = ''; + var walkerOffset = 0; + var newWalkerOffset; + + if (!offsetList.length) { + return result; + } + + var offset = offsetList.shift(); + var walker = document.createTreeWalker(root, 4, null, false); + + while (walker.nextNode()) { + text = walker.currentNode.nodeValue || ''; + + if (textNodeFilter) { + text = textNodeFilter(text); + } + + newWalkerOffset = walkerOffset + text.length; + + while (newWalkerOffset >= offset) { + result.push({ + container: walker.currentNode, + offsetInContainer: offset - walkerOffset, + offset: offset + }); + + if (!offsetList.length) { + return result; + } + + offset = offsetList.shift(); + } + + walkerOffset = newWalkerOffset; + } // there should be offset left + + + do { + result.push({ + container: walker.currentNode, + offsetInContainer: text.length, + offset: offset + }); + offset = offsetList.shift(); + } while (!tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(offset)); + + return result; +}; + +var getNodeInfo = function getNodeInfo(node) { + var path = {}; + path.tagName = node.nodeName; + + if (node.id) { + path.id = node.id; + } + + var className = node.className.trim(); + + if (className) { + path.className = className; + } + + return path; +}; + +var getPath = function getPath(node, root) { + var paths = []; + + while (node && node !== root) { + if (isElemNode(node)) { + paths.unshift(getNodeInfo(node)); + } + + node = node.parentNode; + } + + return paths; +}; +/** + * Find next, previous TD or TH element by given TE element + * @param {HTMLElement} node TD element + * @param {string} direction 'next' or 'previous' + * @returns {HTMLElement|null} + * @ignore + */ + + +var getTableCellByDirection = function getTableCellByDirection(node, direction) { + var targetElement = null; + + if (!tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(direction) && (direction === 'next' || direction === 'previous')) { + if (direction === 'next') { + targetElement = node.nextElementSibling; + } else { + targetElement = node.previousElementSibling; + } + } + + return targetElement; +}; +/** + * Find sibling TR's TD element by given TD and direction + * @param {HTMLElement} node TD element + * @param {string} direction Boolean value for find first TD in next line + * @param {boolean} [needEdgeCell=false] Boolean value for find first TD in next line + * @returns {HTMLElement|null} + * @ignore + */ + + +var getSiblingRowCellByDirection = function getSiblingRowCellByDirection(node, direction, needEdgeCell) { + var tableCellElement = null; + var index, targetRowElement, currentContainer, siblingContainer, isSiblingContainerExists; + + if (!tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(direction) && (direction === 'next' || direction === 'previous')) { + if (node) { + if (direction === 'next') { + targetRowElement = node.parentNode && node.parentNode.nextSibling; + currentContainer = parents(node, 'thead'); + siblingContainer = currentContainer[0] && currentContainer[0].nextSibling; + isSiblingContainerExists = siblingContainer && getNodeName(siblingContainer) === 'TBODY'; + index = 0; + } else { + targetRowElement = node.parentNode && node.parentNode.previousSibling; + currentContainer = parents(node, 'tbody'); + siblingContainer = currentContainer[0] && currentContainer[0].previousSibling; + isSiblingContainerExists = siblingContainer && getNodeName(siblingContainer) === 'THEAD'; + index = node.parentNode.childNodes.length - 1; + } + + if (tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(needEdgeCell) || !needEdgeCell) { + index = getNodeOffsetOfParent(node); + } + + if (targetRowElement) { + tableCellElement = children(targetRowElement, 'td,th')[index]; + } else if (currentContainer[0] && isSiblingContainerExists) { + tableCellElement = findAll(siblingContainer, 'td,th')[index]; + } + } + } + + return tableCellElement; +}; +/** + * Check that the inline node is supported by markdown + * @param {Node} node TD element + * @returns {boolean} + * @ignore + */ + + +var isMDSupportInlineNode = function isMDSupportInlineNode(node) { + return /^(A|B|BR|CODE|DEL|EM|I|IMG|S|SPAN|STRONG)$/gi.test(node.nodeName); +}; +/** + * Check that node is styled node. + * Styled node is a node that has text and decorates text. + * @param {Node} node TD element + * @returns {boolean} + * @ignore + */ + + +var isStyledNode = function isStyledNode(node) { + return /^(A|ABBR|ACRONYM|B|BDI|BDO|BIG|CITE|CODE|DEL|DFN|EM|I|INS|KBD|MARK|Q|S|SAMP|SMALL|SPAN|STRONG|SUB|SUP|U|VAR)$/gi.test(node.nodeName); +}; +/** + * remove node from 'start' node to 'end-1' node inside parent + * if 'end' node is null, remove all child nodes after 'start' node. + * @param {Node} parentNode - parent node + * @param {Node} start - start node to remove + * @param {Node} end - end node to remove + * @ignore + */ + + +var removeChildFromStartToEndNode = function removeChildFromStartToEndNode(parentNode, start, end) { + var child = start; + + if (!child || parentNode !== child.parentNode) { + return; + } + + while (child !== end) { + var nextNode = child.nextSibling; + parentNode.removeChild(child); + child = nextNode; + } +}; +/** + * remove nodes along the direction from the node to reach targetParent node + * @param {Node} targetParent - stop removing when reach target parent node + * @param {Node} node - start node + * @param {boolean} isForward - direction + * @ignore + */ + + +var removeNodesByDirection = function removeNodesByDirection(targetParent, node, isForward) { + var parentNode = node; + + while (parentNode !== targetParent) { + var nextParent = parentNode.parentNode; + var _parentNode = parentNode, + nextSibling = _parentNode.nextSibling, + previousSibling = _parentNode.previousSibling; + + if (!isForward && nextSibling) { + removeChildFromStartToEndNode(nextParent, nextSibling, null); + } else if (isForward && previousSibling) { + removeChildFromStartToEndNode(nextParent, nextParent.childNodes[0], parentNode); + } + + parentNode = nextParent; + } +}; + +var getLeafNode = function getLeafNode(node) { + var result = node; + + while (result.childNodes && result.childNodes.length) { + var _result = result, + nextLeaf = _result.firstChild; // When inline tag have empty text node with other childnodes, ignore empty text node. + + if (isTextNode(nextLeaf) && !getTextLength(nextLeaf)) { + result = nextLeaf.nextSibling || nextLeaf; + } else { + result = nextLeaf; + } + } + + return result; +}; +/** + * check if a coordinates is inside a button box + * @param {object} style - computed style of task box + * @param {number} offsetX - event x offset + * @param {number} offsetY - event y offset + * @returns {boolean} + * @ignore + */ + + +var isInsideButtonBox = function isInsideButtonBox(style, offsetX, offsetY) { + var rect = { + left: parseInt(style.left, 10), + top: parseInt(style.top, 10), + width: parseInt(style.width, 10), + height: parseInt(style.height, 10) + }; + return offsetX >= rect.left && offsetX <= rect.left + rect.width && offsetY >= rect.top && offsetY <= rect.top + rect.height; +}; +/** + * Check whether node is OL or UL + * @param {node} node - node + * @returns {boolean} - whether node is OL or UL + * @ignore + */ + + +var isListNode = function isListNode(node) { + if (!node) { + return false; + } + + return node.nodeName === 'UL' || node.nodeName === 'OL'; +}; +/** + * Check whether node is first list item + * @param {node} node - node + * @returns {boolean} whether node is first list item + * @ignore + */ + + +var isFirstListItem = function isFirstListItem(node) { + var nodeName = node.nodeName, + parentNode = node.parentNode; + return nodeName === 'LI' && node === parentNode.firstChild; +}; +/** + * Check whether node is first level list item + * @param {node} node - node + * @returns {boolean} whether node is first level list item + * @ignore + */ + + +var isFirstLevelListItem = function isFirstLevelListItem(node) { + var nodeName = node.nodeName, + listNode = node.parentNode; + var listParentNode = listNode.parentNode; + return nodeName === 'LI' && !isListNode(listParentNode); +}; +/** + * Merge node to target node and detach node + * @param {node} node - node + * @param {node} targetNode - target node + * @ignore + */ + + +var mergeNode = function mergeNode(node, targetNode) { + if (node.hasChildNodes()) { + tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(node.childNodes).forEach(function () { + targetNode.appendChild(node.firstChild); + }); + targetNode.normalize(); + } + + if (node.parentNode) { + node.parentNode.removeChild(node); + } +}; +/** + * Create hr that is not contenteditable + * @returns {node} hr is wraped div + * @ignore + */ + + +var createHorizontalRule = function createHorizontalRule() { + var div = document.createElement('div'); + var hr = document.createElement('hr'); + div.setAttribute('contenteditable', false); + hr.setAttribute('contenteditable', false); + div.appendChild(hr); + return div; +}; +/** + * Create Empty Line + * @returns {node}

+ * @private + */ + + +var createEmptyLine = function createEmptyLine() { + var div = document.createElement('div'); + div.appendChild(document.createElement('br')); + return div; +}; +/** + * Find same tagName child node and change wrapping order. + * For example, if below node need to optimize 'B' tag. + * test + * should be changed tag's order. + * test + * @param {node} node + * @param {string} tagName + * @returns {node} + * @private + */ + + +var changeTagOrder = function changeTagOrder(node, tagName) { + if (node.nodeName !== 'SPAN') { + var parentNode = node.parentNode; + var tempNode = node; + + while (tempNode.childNodes && tempNode.childNodes.length === 1 && !isTextNode(tempNode.firstChild)) { + tempNode = tempNode.firstChild; + + if (tempNode.nodeName === 'SPAN') { + break; + } + + if (tempNode.nodeName === tagName) { + var wrapper = document.createElement(tagName); + mergeNode(tempNode, tempNode.parentNode); + parentNode.replaceChild(wrapper, node); + wrapper.appendChild(node); + return wrapper; + } + } + } + + return node; +}; +/** + * Find same tagName nodes and merge from startNode to endNode. + * @param {node} startNode + * @param {node} endNode + * @param {string} tagName + * @returns {node} + * @private + */ + + +var mergeSameNodes = function mergeSameNodes(startNode, endNode, tagName) { + var startBlockNode = changeTagOrder(startNode, tagName); + + if (startBlockNode.nodeName === tagName) { + var endBlockNode = changeTagOrder(endNode, tagName); + var mergeTargetNode = startBlockNode; + var nextNode = startBlockNode.nextSibling; + + while (nextNode) { + var tempNext = nextNode.nextSibling; + nextNode = changeTagOrder(nextNode, tagName); + + if (nextNode.nodeName === tagName) { + // eslint-disable-next-line max-depth + if (mergeTargetNode) { + mergeNode(nextNode, mergeTargetNode); + } else { + mergeTargetNode = nextNode; + } + } else { + mergeTargetNode = null; + } + + if (nextNode === endBlockNode) { + break; + } + + nextNode = tempNext; + } + } +}; +/** + * Find same tagName nodes in range and merge nodes. + * For example range is like this + * AAABBB + * nodes is changed below + * AAABBB + * @param {range} range + * @param {string} tagName + * @private + */ + + +var optimizeRange = function optimizeRange(range, tagName) { + var collapsed = range.collapsed, + commonAncestorContainer = range.commonAncestorContainer, + startContainer = range.startContainer, + endContainer = range.endContainer; + + if (!collapsed) { + var optimizedNode = null; + + if (startContainer !== endContainer) { + var startNode = getParentUntil(startContainer, commonAncestorContainer); + var endNode = getParentUntil(endContainer, commonAncestorContainer); + + if (startNode && endNode) { + mergeSameNodes(startNode, endNode, tagName); + } + + optimizedNode = commonAncestorContainer; + } else if (isTextNode(startContainer)) { + optimizedNode = startContainer.parentNode; + } + + if (optimizedNode && optimizedNode.nodeName === tagName) { + var _optimizedNode = optimizedNode, + previousSibling = _optimizedNode.previousSibling; + var tempNode; + + if (previousSibling) { + tempNode = changeTagOrder(previousSibling); + + if (tempNode.nodeName === tagName) { + mergeNode(optimizedNode, tempNode); + } + } + + var _optimizedNode2 = optimizedNode, + nextSibling = _optimizedNode2.nextSibling; + + if (nextSibling) { + tempNode = changeTagOrder(nextSibling); + + if (tempNode.nodeName === tagName) { + mergeNode(tempNode, optimizedNode); + } + } + } + } +}; +/** + * Gets all text node from root element. + * @param {HTMLElement} root Root element + * @returns {Array} list of text nodes + * @ignore + */ + + +var getAllTextNode = function getAllTextNode(root) { + var walker = document.createTreeWalker(root, 4, null, false); + var result = []; + + while (walker.nextNode()) { + var node = walker.currentNode; + + if (isTextNode(node)) { + result.push(node); + } + } + + return result; +}; +/** + * Check whether the node is 'TD' or 'TH' + * @param {HTMLElement} node - the target node + * @returns {boolean} - whether the node is 'TD' or 'TH' + * @ignore + */ + + +var isCellNode = function isCellNode(node) { + if (!node) { + return false; + } + + return node.nodeName === 'TD' || node.nodeName === 'TH'; +}; +/** + * Get the last node on the target node by the condition + * @param {HTMLElement} node - the target node + * @returns {function} - the condition to find the node + * @ignore + */ + + +var getLastNodeBy = function getLastNodeBy(node, condition) { + var lastNode = node && node.lastChild; + + while (lastNode && condition(lastNode)) { + lastNode = lastNode.lastChild; + } + + return lastNode; +}; +/** + * Get the parent node on the target node by the condition + * @param {HTMLElement} node - the target node + * @returns {function} - the condition to find the node + * @ignore + */ + + +var getParentNodeBy = function getParentNodeBy(node, condition) { + while (node && condition(node.parentNode, node)) { + node = node.parentNode; + } + + return node; +}; +/** + * Get the sibling node on the target node by the condition + * @param {HTMLElement} node - the target node + * @param {string} direction - the direction to find node ('previous', 'next') + * @returns {function} - the condition to find the node + * @ignore + */ + + +var getSiblingNodeBy = function getSiblingNodeBy(node, direction, condition) { + var directionKey = direction + "Sibling"; + + while (node && condition(node[directionKey], node)) { + node = node[directionKey]; + } + + return node; +}; +/** + * Create element with contents + * @param {string|Node} contents - contents to appended + * @param {HTMLElement} [target] - container element to append contents + * @returns {Node} created node + * @ignore + */ + + +function createElementWith(contents, target) { + var container = document.createElement('div'); + + if (tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default()(contents)) { + container.innerHTML = contents; + } else { + container.appendChild(contents); + } + + var firstChild = container.firstChild; + + if (target) { + target.appendChild(firstChild); + } + + return firstChild; +} +/** + * Find nodes matching by selector + * @param {HTMLElement} element - target element + * @param {string} selector - selector to find nodes + * @returns {Array.} found nodes + * @ignore + */ + + +function findAll(element, selector) { + var nodeList = tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(element.querySelectorAll(selector)); + + if (nodeList.length) { + return nodeList; + } + + return []; +} +/** + * Checks whether specific node is included in target node + * @param {HTMLElement} element - target to find + * @param {Node} containedNode - node to find + * @returns {boolean} whether node is contained or not + * @ignore + */ + + +function isContain(element, contained) { + return element !== contained && element.contains(contained); +} +/** + * Gets closest node matching by selector + * @param {Node} node - target node + * @param {string|Node} found - selector or element to find node + * @param {Node} [root] - root node + * @returns {?Node} - found node + * @ignore + */ + + +function closest(node, found, root) { + var condition; + root = root || document; + + if (tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default()(found)) { + condition = function condition(target) { + return tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default()(target, found); + }; + } else { + condition = function condition(target) { + return target === found; + }; + } + + while (node && node !== root) { + if (isElemNode(node) && condition(node)) { + return node; + } + + node = node.parentNode; + } + + return null; +} +/** + * Gets parent node matching by selector from target node + * @param {Node} node - target node + * @param {string} [selector] - selector to find + * @returns {Node} found node + * @ignore + */ + + +function parent(node, selector) { + var parentNode = node.parentNode; + + if (selector) { + return parentNode && tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default()(parentNode, selector) ? parentNode : null; + } + + return parentNode; +} +/** + * Gets ancestor nodes matching by selector from target node + * @param {Node} node - target node + * @param {string|Node} found - selector or node to find + * @returns {Array.} found nodes + * @ignore + */ + + +function parents(node, found) { + var result = []; + + while (node && node !== document) { + node = closest(node.parentNode, found); + + if (node) { + result.push(node); + } + } + + return result; +} +/** + * Gets ancestor nodes until matching by selector from target node + * @param {Node} node - target node + * @param {string} selector - selector to find + * @param {Array.} found nodes + * @ignore + */ + + +function parentsUntil(node, selector) { + var result = []; + + while (node.parentNode && !tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default()(node.parentNode, selector)) { + node = node.parentNode; + + if (node) { + result.push(node); + } + } + + return result; +} +/** + * Gets child nodes matching by selector from target node + * @param {Node} node - target node + * @param {string} selector - selector to find + * @returns {Array.} found nodes + * @ignore + */ + + +function children(node, selector) { + var foundChildren; + + if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { + foundChildren = node.childNodes; + } else { + foundChildren = node.children; + } + + return tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(foundChildren).filter(function (child) { + return tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default()(child, selector); + }); +} +/** + * Appends node(s) on target node + * @param {Node} node - target node + * @param {string|Node} appended - html string or node to append + * @ignore + */ + + +function append(node, appended) { + if (tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default()(appended)) { + node.insertAdjacentHTML('beforeEnd', appended); + } else { + appended = appended.length ? tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(appended) : [appended]; + + for (var i = 0, len = appended.length; i < len; i += 1) { + node.appendChild(appended[i]); + } + } +} +/** + * Prepends node(s) on target node + * @param {Node} node - target node + * @param {string|Node} appended - html string or node to append + * @ignore + */ + + +function prepend(node, appended) { + if (tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default()(appended)) { + node.insertAdjacentHTML('afterBegin', appended); + } else { + appended = appended.length ? tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(appended) : [appended]; + + for (var i = appended.length - 1, len = 0; i >= len; i -= 1) { + node.insertBefore(appended[i], node.firstChild); + } + } +} +/** + * Inserts new node in front of target node + * @param {Node} insertedNode - node to insert + * @param {Node} node - target node + * @ignore + */ + + +function insertBefore(insertedNode, node) { + var parentNode = node.parentNode; + + if (parentNode) { + parentNode.insertBefore(insertedNode, node); + } +} +/** + * Inserts new node after target node + * @param {Node} insertedNode - node to insert + * @param {Node} node - target node + * @ignore + */ + + +function insertAfter(insertedNode, node) { + var parentNode = node.parentNode; + + if (parentNode) { + parentNode.insertBefore(insertedNode, node.nextSibling); + } +} +/** + * Replaces target node(s) with html + * @param {Node} nodeList - target node(s) to replace + * @param {string} html - replaced html + * @ignore + */ + + +function replaceWith(nodeList, html) { + nodeList = nodeList.length ? tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(nodeList) : [nodeList]; + nodeList.forEach(function (node) { + node.insertAdjacentHTML('afterEnd', html); + node.parentNode.removeChild(node); + }); +} +/** + * Adds parent element to target node(s) + * @param {Node|Array.} nodeList - target node(s) + * @param {string} nodeName - node name to change parent element + * @ignore + */ + + +function wrap(nodeList, nodeName) { + nodeList = nodeList.length ? tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(nodeList) : [nodeList]; + nodeList.forEach(function (node) { + var wrapper = document.createElement(nodeName); + node.parentNode.insertBefore(wrapper, node); + wrapper.appendChild(node); + }); +} +/** + * Adds child element to target node(s) + * @param {Node|Array.} nodeList - target node(s) + * @param {string} nodeName - node name to change child element + * @ignore + */ + + +function wrapInner(nodeList, nodeName) { + nodeList = nodeList.length ? tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(nodeList) : [nodeList]; + nodeList.forEach(function (node) { + var wrapper = document.createElement(nodeName); + node.appendChild(wrapper); + + while (node.firstChild !== wrapper) { + wrapper.appendChild(node.firstChild); + } + }); +} +/** + * Removes target element and insert children at the same position + * @param {Node} node - parent node + * @returns {Array.} unwrapped nodes + * @ignore + */ + + +function unwrap(node) { + var result = []; + + while (node.firstChild) { + result.push(node.firstChild); + node.parentNode.insertBefore(node.firstChild, node); + } + + remove(node); + return result; +} +/** + * Removes target node from parent node + * @param {Node} node - target node + * @ignore + */ + + +function remove(node) { + if (node.parentNode) { + node.parentNode.removeChild(node); + } +} +/** + * Removes all children of target node + * @param {Node} node - target node + * @ignore + */ + + +function empty(node) { + while (node.firstChild) { + node.removeChild(node.firstChild); + } +} +/** + * Sets offset value of target element + * @param {HTMLElement} element - target element + * @returns {Object.} offset values + * @ignore + */ + + +function setOffset(element, offset) { + var _element$parentNode$g = element.parentNode.getBoundingClientRect(), + top = _element$parentNode$g.top, + left = _element$parentNode$g.left; + + tui_code_snippet_domUtil_css__WEBPACK_IMPORTED_MODULE_3___default()(element, { + top: offset.top - top - document.body.scrollTop + "px" + }); + tui_code_snippet_domUtil_css__WEBPACK_IMPORTED_MODULE_3___default()(element, { + left: offset.left - left - document.body.scrollLeft + "px" + }); +} +/** + * Gets offset value of target element + * @param {HTMLElement} element - target element + * @param {string} [selector] - selector to stop finding node + * @returns {Object.} offset values + * @ignore + */ + + +function getOffset(element, selector) { + if (selector === void 0) { + selector = 'document'; + } + + var top = 0; + var left = 0; + + do { + top += element.offsetTop || 0; + left += element.offsetLeft || 0; + element = element.offsetParent; + } while (element && !tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default()(element, selector)); + + return { + top: top, + left: left + }; +} +/** + * Gets outer width value of target element + * @param {HTMLElement} element - target element + * @param {boolean} includedMargin - whether to include margir or not + * @returns {number} outer width value + * @ignore + */ + + +function getOuterWidth(element, includedMargin) { + var widthValue = element.offsetWidth; + + if (includedMargin) { + var _getComputedStyle = getComputedStyle(element), + marginLeft = _getComputedStyle.marginLeft, + marginRight = _getComputedStyle.marginRight; + + widthValue += parseInt(marginLeft, 10) + parseInt(marginRight, 10); + } + + return widthValue; +} +/** + * Gets outer height value of target element + * @param {HTMLElement} element - target element + * @param {boolean} includedMargin - whether to include margir or not + * @returns {number} outer height value + * @ignore + */ + + +function getOuterHeight(element, includedMargin) { + var heightValue = element.offsetHeight; + + if (includedMargin) { + var _getComputedStyle2 = getComputedStyle(element), + marginTop = _getComputedStyle2.marginTop, + marginBottom = _getComputedStyle2.marginBottom; + + heightValue += parseInt(marginTop, 10) + parseInt(marginBottom, 10); + } + + return heightValue; +} +/** + * Toggles class name of target element + * @param {HTMLElement} element - target element + * @param {string} className - class name to toggle + * @param {boolean} [state] - whether to toggle or not by condition + * @ignore + */ + + +var toggleClass = function toggleClass(element, className, state) { + if (tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(state)) { + state = !tui_code_snippet_domUtil_hasClass__WEBPACK_IMPORTED_MODULE_6___default()(element, className); + } + + var toggleFn = state ? tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_4___default.a : tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_5___default.a; + toggleFn(element, className); +}; +/** + * Finalize html result + * @param {HTMLElement} html root element + * @param {boolean} needHtmlText pass true if need html text + * @returns {string|DocumentFragment} result + * @ignore + */ + + +function finalizeHtml(html, needHtmlText) { + var result; + + if (needHtmlText) { + result = html.innerHTML; + } else { + var frag = document.createDocumentFragment(); + var childNodes = tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(html.childNodes); + var length = childNodes.length; + + for (var i = 0; i < length; i += 1) { + frag.appendChild(childNodes[i]); + } + + result = frag; + } + + return result; +} +/** + * Get fragment replaced by newline to br tag + * @param {string} text original text + * @returns {DocumentFragment} fragment + * @ignore + */ + + +function getFragmentReplacedByNewlineToBr(text) { + var fragment = document.createDocumentFragment(); + var texts = text.split('\n'); + texts.forEach(function (plainText, index) { + var textNode = document.createTextNode(plainText); + fragment.appendChild(textNode); + + if (index < texts.length - 1) { + fragment.appendChild(document.createElement('br')); + } + }); + return fragment; +} + +/* harmony default export */ __webpack_exports__["a"] = ({ + getNodeName: getNodeName, + isTextNode: isTextNode, + isElemNode: isElemNode, + isBlockNode: isBlockNode, + getTextLength: getTextLength, + getOffsetLength: getOffsetLength, + getPrevOffsetNodeUntil: getPrevOffsetNodeUntil, + getNodeOffsetOfParent: getNodeOffsetOfParent, + getChildNodeByOffset: getChildNodeByOffset, + getNodeWithDirectionUntil: getNodeWithDirectionUntil, + containsNode: containsNode, + getTopPrevNodeUnder: getTopPrevNodeUnder, + getTopNextNodeUnder: getTopNextNodeUnder, + getParentUntilBy: getParentUntilBy, + getParentUntil: getParentUntil, + getTopBlockNode: getTopBlockNode, + getPrevTextNode: getPrevTextNode, + findOffsetNode: findOffsetNode, + getPath: getPath, + getNodeInfo: getNodeInfo, + getTableCellByDirection: getTableCellByDirection, + getSiblingRowCellByDirection: getSiblingRowCellByDirection, + isMDSupportInlineNode: isMDSupportInlineNode, + isStyledNode: isStyledNode, + removeChildFromStartToEndNode: removeChildFromStartToEndNode, + removeNodesByDirection: removeNodesByDirection, + getLeafNode: getLeafNode, + isInsideButtonBox: isInsideButtonBox, + isListNode: isListNode, + isFirstListItem: isFirstListItem, + isFirstLevelListItem: isFirstLevelListItem, + mergeNode: mergeNode, + createHorizontalRule: createHorizontalRule, + createEmptyLine: createEmptyLine, + changeTagOrder: changeTagOrder, + mergeSameNodes: mergeSameNodes, + optimizeRange: optimizeRange, + getAllTextNode: getAllTextNode, + isCellNode: isCellNode, + getLastNodeBy: getLastNodeBy, + getParentNodeBy: getParentNodeBy, + getSiblingNodeBy: getSiblingNodeBy, + createElementWith: createElementWith, + findAll: findAll, + isContain: isContain, + closest: closest, + parent: parent, + parents: parents, + parentsUntil: parentsUntil, + children: children, + append: append, + prepend: prepend, + insertBefore: insertBefore, + insertAfter: insertAfter, + replaceWith: replaceWith, + wrap: wrap, + wrapInner: wrapInner, + unwrap: unwrap, + remove: remove, + empty: empty, + setOffset: setOffset, + getOffset: getOffset, + getOuterWidth: getOuterWidth, + getOuterHeight: getOuterHeight, + toggleClass: toggleClass, + finalizeHtml: finalizeHtml, + getFragmentReplacedByNewlineToBr: getFragmentReplacedByNewlineToBr +}); + +/***/ }), +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/object/extend.js +var extend = __webpack_require__(7); +var extend_default = /*#__PURE__*/__webpack_require__.n(extend); + +// CONCATENATED MODULE: ./src/js/command.js +/** + * @fileoverview Implements Command + * @author NHN FE Development Lab + */ + +/** + * Class Command + * @param {string} name Command name + * @param {number} type Command type (Command.TYPE) + * @param {Array.} [keyMap] keyMap + * @ignore + */ + +var Command = /*#__PURE__*/function () { + function Command(name, type, keyMap) { + this.name = name; + this.type = type; + + if (keyMap) { + this.setKeyMap(keyMap); + } + } + /** + * returns Name of command + * @returns {string} Command Name + */ + + + var _proto = Command.prototype; + + _proto.getName = function getName() { + return this.name; + } + /** + * returns Type of command + * @returns {number} Command Command type number + */ + ; + + _proto.getType = function getType() { + return this.type; + } + /** + * returns whether Command Type is Markdown or not + * @returns {boolean} result + */ + ; + + _proto.isMDType = function isMDType() { + return this.type === Command.TYPE.MD; + } + /** + * returns whether Command Type is Wysiwyg or not + * @returns {boolean} result + */ + ; + + _proto.isWWType = function isWWType() { + return this.type === Command.TYPE.WW; + } + /** + * returns whether Command Type is Global or not + * @returns {boolean} result + */ + ; + + _proto.isGlobalType = function isGlobalType() { + return this.type === Command.TYPE.GB; + } + /** + * Set keymap value for each os + * @param {string} win Windows Key(and etc) + * @param {string} mac Mac osx key + */ + ; + + _proto.setKeyMap = function setKeyMap(win, mac) { + this.keyMap = [win, mac]; + }; + + return Command; +}(); +/** + * Command factory method + * @param {string} typeStr Editor type name + * @param {object} props Property + * @param {string} props.name Command name + * @param {number} props.type Command type number + * @returns {Command} + * @static + */ + + +Command.factory = function (typeStr, props) { + var type; + + if (typeStr === 'markdown') { + type = Command.TYPE.MD; + } else if (typeStr === 'wysiwyg') { + type = Command.TYPE.WW; + } else if (typeStr === 'global') { + type = Command.TYPE.GB; + } + + var command = new Command(props.name, type); + extend_default()(command, props); + return command; +}; +/** + * Command Type Constant + * markdown : 0 + * wysiwyg : 1 + * global : 2 + * @type {object} + * @private + */ + + +Command.TYPE = { + MD: 0, + WW: 1, + GB: 2 +}; +/* harmony default export */ var js_command = (Command); +// EXTERNAL MODULE: ./src/js/utils/common.js +var common = __webpack_require__(12); + +// EXTERNAL MODULE: ./src/js/utils/map.js +var map = __webpack_require__(23); + +// CONCATENATED MODULE: ./src/js/commandManager.js +/** + * @fileoverview Implements CommandManager + * @author NHN FE Development Lab + */ + + + + +var KEYMAP_OS_INDEX = common["b" /* isMac */] ? 1 : 0; +/** + * Class CommandManager + * @param {ToastUIEditor} base nedInstance + * @param {object} [options={}] - option object + * @param {boolean} [options.useCommandShortcut=true] - execute command with keyMap + * @ignore + */ + +var commandManager_CommandManager = /*#__PURE__*/function () { + function CommandManager(base, options) { + if (options === void 0) { + options = {}; + } + + this._command = new map["a" /* default */](); + this._mdCommand = new map["a" /* default */](); + this._wwCommand = new map["a" /* default */](); + this._options = extend_default()({ + useCommandShortcut: true + }, options); + this.base = base; + this.keyMapCommand = {}; + + this._initEvent(); + } + /** + * You can change command before command addition by addCommandBefore event. + * @param {object} command - command + * @returns {object} + * @private + */ + + + var _proto = CommandManager.prototype; + + _proto._addCommandBefore = function _addCommandBefore(command) { + var commandWrapper = { + command: command + }; + this.base.eventManager.emit('addCommandBefore', commandWrapper); + return commandWrapper.command || command; + } + /** + * Add command + * @param {Command} command Command instance + * @returns {Command} Command + */ + ; + + _proto.addCommand = function addCommand(command) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + if (args.length) { + command = CommandManager.command.apply(CommandManager, [command].concat(args)); + } + + command = this._addCommandBefore(command); + var name = command.getName(); + var commandBase; + + if (command.isMDType()) { + commandBase = this._mdCommand; + } else if (command.isWWType()) { + commandBase = this._wwCommand; + } else if (command.isGlobalType()) { + commandBase = this._command; + } + + commandBase.set(name, command); + + if (command.keyMap) { + this.keyMapCommand[command.keyMap[KEYMAP_OS_INDEX]] = name; + } + + return command; + } + /** + * _initEvent + * Bind event handler to eventManager + * @private + */ + ; + + _proto._initEvent = function _initEvent() { + var _this = this; + + this.base.eventManager.listen('command', function () { + _this.exec.apply(_this, arguments); + }); + this.base.eventManager.listen('keyMap', function (ev) { + if (!_this._options.useCommandShortcut) { + return; + } + + var command = _this.keyMapCommand[ev.keyMap]; + + if (command) { + ev.data.preventDefault(); + + _this.exec(command); + } + }); + } + /** + * Execute command + * @param {String} name Command name + * @param {*} ...args Command argument + * @returns {*} + */ + ; + + _proto.exec = function exec(name) { + var commandToRun, result; + var context = this.base; + commandToRun = this._command.get(name); + + if (!commandToRun) { + if (this.base.isMarkdownMode()) { + commandToRun = this._mdCommand.get(name); + context = this.base.mdEditor; + } else { + commandToRun = this._wwCommand.get(name); + context = this.base.wwEditor; + } + } + + if (commandToRun) { + var _commandToRun; + + for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { + args[_key2 - 1] = arguments[_key2]; + } + + args.unshift(context); + result = (_commandToRun = commandToRun).exec.apply(_commandToRun, args); + } + + return result; + }; + + return CommandManager; +}(); +/** + * Create command by given editor type and property object + * @param {string} type Command type + * @param {{name: string, keyMap: Array}} props Property + * @returns {*} + * @static + */ + + +commandManager_CommandManager.command = function (type, props) { + var command = js_command.factory(type, props.name, props.keyMap); + extend_default()(command, props); + return command; +}; + +/* harmony default export */ var commandManager = __webpack_exports__["a"] = (commandManager_CommandManager); + +/***/ }), +/* 2 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export hasImageOrCodeBlockNode */ +/* unused harmony export hasSameLineParent */ +/* unused harmony export hasSpecificTypeAncestor */ +/* unused harmony export isEmptyLineNode */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return getMdStartLine; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return getMdEndLine; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return getMdStartCh; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return getMdEndCh; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "j", function() { return isMultiLineNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return isHtmlNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "k", function() { return isStyledTextNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return isListItemNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "l", function() { return isTableCellNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return isInlineNode; }); +/* unused harmony export getLastLeafNode */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return findClosestNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "n", function() { return traverseParentNodes; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return addChPos; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "m", function() { return setChPos; }); +/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); + +function hasImageOrCodeBlockNode(mdNode) { + while (mdNode) { + if (Object(_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(['image', 'codeBlock'], mdNode.type)) { + return true; + } + + mdNode = mdNode.firstChild; + } + + return false; +} +function hasSameLineParent(mdNode) { + return mdNode.parent && mdNode.parent.type !== 'document' && mdNode.parent.sourcepos[0][0] === mdNode.sourcepos[0][0]; +} +function hasSpecificTypeAncestor(mdNode) { + for (var _len = arguments.length, types = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + types[_key - 1] = arguments[_key]; + } + + while (mdNode.parent && mdNode.parent.type !== 'document') { + if (Object(_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(types, mdNode.parent.type)) { + return true; + } + + mdNode = mdNode.parent; + } + + return false; +} +function isEmptyLineNode(text, mdNode) { + return !text.trim() && !hasImageOrCodeBlockNode(mdNode); +} +function getMdStartLine(mdNode) { + return mdNode.sourcepos[0][0]; +} +function getMdEndLine(mdNode) { + return mdNode.sourcepos[1][0]; +} +function getMdStartCh(mdNode) { + return mdNode.sourcepos[0][1]; +} +function getMdEndCh(mdNode) { + return mdNode.sourcepos[1][1]; +} +function isMultiLineNode(mdNode) { + var type = mdNode.type; + return type === 'codeBlock' || type === 'paragraph'; +} +function isHtmlNode(mdNode) { + var type = mdNode.type; + return type === 'htmlBlock' || type === 'htmlInline'; +} +function isStyledTextNode(mdNode) { + var type = mdNode.type; + return type === 'strike' || type === 'strong' || type === 'emph'; +} +function isListItemNode(mdNode) { + return mdNode.type === 'item'; +} +function isTableCellNode(mdNode) { + var type = mdNode.type; + return type === 'tableCell' || type === 'tableDelimCell'; +} +function isInlineNode(mdNode) { + switch (mdNode.type) { + case 'code': + case 'text': + case 'emph': + case 'strong': + case 'strike': + case 'link': + case 'image': + case 'htmlInline': + case 'linebreak': + case 'softbreak': + return true; + + default: + return false; + } +} +function getLastLeafNode(mdNode) { + while (mdNode.lastChild) { + mdNode = mdNode.lastChild; + } + + return mdNode; +} +function findClosestNode(mdNode, condition, includeSelf) { + if (includeSelf === void 0) { + includeSelf = true; + } + + mdNode = includeSelf ? mdNode : mdNode.parent; + + while (mdNode && mdNode.type !== 'document') { + if (condition(mdNode)) { + return mdNode; + } + + mdNode = mdNode.parent; + } + + return null; +} +function traverseParentNodes(mdNode, iteratee, includeSelf) { + if (includeSelf === void 0) { + includeSelf = true; + } + + mdNode = includeSelf ? mdNode : mdNode.parent; + + while (mdNode && mdNode.type !== 'document') { + iteratee(mdNode); + mdNode = mdNode.parent; + } +} +function addChPos(originPos, addedCh) { + return { + line: originPos.line, + ch: originPos.ch + addedCh + }; +} +function setChPos(originPos, newCh) { + return { + line: originPos.line, + ch: newCh + }; +} + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Transform the Array-like object to Array. + * @author NHN FE Development Lab + */ + + + +var forEachArray = __webpack_require__(21); + +/** + * Transform the Array-like object to Array. + * In low IE (below 8), Array.prototype.slice.call is not perfect. So, try-catch statement is used. + * @param {*} arrayLike Array-like object + * @returns {Array} Array + * @memberof module:collection + * @example + * var toArray = require('tui-code-snippet/collection/toArray'); // node, commonjs + * + * var arrayLike = { + * 0: 'one', + * 1: 'two', + * 2: 'three', + * 3: 'four', + * length: 4 + * }; + * var result = toArray(arrayLike); + * + * alert(result instanceof Array); // true + * alert(result); // one,two,three,four + */ +function toArray(arrayLike) { + var arr; + try { + arr = Array.prototype.slice.call(arrayLike); + } catch (e) { + arr = []; + forEachArray(arrayLike, function(value) { + arr.push(value); + }); + } + + return arr; +} + +module.exports = toArray; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Setting element style + * @author NHN FE Development Lab + */ + + + +var isString = __webpack_require__(9); +var forEach = __webpack_require__(26); + +/** + * Setting element style + * @param {(HTMLElement|SVGElement)} element - element to setting style + * @param {(string|object)} key - style prop name or {prop: value} pair object + * @param {string} [value] - style value + * @memberof module:domUtil + */ +function css(element, key, value) { + var style = element.style; + + if (isString(key)) { + style[key] = value; + + return; + } + + forEach(key, function(v, k) { + style[k] = v; + }); +} + +module.exports = css; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Add css class to element + * @author NHN FE Development Lab + */ + + + +var forEach = __webpack_require__(26); +var inArray = __webpack_require__(14); +var getClass = __webpack_require__(33); +var setClassName = __webpack_require__(39); + +/** + * domUtil module + * @module domUtil + */ + +/** + * Add css class to element + * @param {(HTMLElement|SVGElement)} element - target element + * @param {...string} cssClass - css classes to add + * @memberof module:domUtil + */ +function addClass(element) { + var cssClass = Array.prototype.slice.call(arguments, 1); + var classList = element.classList; + var newClass = []; + var origin; + + if (classList) { + forEach(cssClass, function(name) { + element.classList.add(name); + }); + + return; + } + + origin = getClass(element); + + if (origin) { + cssClass = [].concat(origin.split(/\s+/), cssClass); + } + + forEach(cssClass, function(cls) { + if (inArray(cls, newClass) < 0) { + newClass.push(cls); + } + }); + + setClassName(element, newClass); +} + +module.exports = addClass; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Remove css class from element + * @author NHN FE Development Lab + */ + + + +var forEachArray = __webpack_require__(21); +var inArray = __webpack_require__(14); +var getClass = __webpack_require__(33); +var setClassName = __webpack_require__(39); + +/** + * Remove css class from element + * @param {(HTMLElement|SVGElement)} element - target element + * @param {...string} cssClass - css classes to remove + * @memberof module:domUtil + */ +function removeClass(element) { + var cssClass = Array.prototype.slice.call(arguments, 1); + var classList = element.classList; + var origin, newClass; + + if (classList) { + forEachArray(cssClass, function(name) { + classList.remove(name); + }); + + return; + } + + origin = getClass(element).split(/\s+/); + newClass = []; + forEachArray(origin, function(name) { + if (inArray(name, cssClass) < 0) { + newClass.push(name); + } + }); + + setClassName(element, newClass); +} + +module.exports = removeClass; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Extend the target object from other objects. + * @author NHN FE Development Lab + */ + + + +/** + * @module object + */ + +/** + * Extend the target object from other objects. + * @param {object} target - Object that will be extended + * @param {...object} objects - Objects as sources + * @returns {object} Extended object + * @memberof module:object + */ +function extend(target, objects) { // eslint-disable-line no-unused-vars + var hasOwnProp = Object.prototype.hasOwnProperty; + var source, prop, i, len; + + for (i = 1, len = arguments.length; i < len; i += 1) { + source = arguments[i]; + for (prop in source) { + if (hasOwnProp.call(source, prop)) { + target[prop] = source[prop]; + } + } + } + + return target; +} + +module.exports = extend; + + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is undefined or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is undefined or not. + * If the given variable is undefined, returns true. + * @param {*} obj - Target for checking + * @returns {boolean} Is undefined? + * @memberof module:type + */ +function isUndefined(obj) { + return obj === undefined; // eslint-disable-line no-undefined +} + +module.exports = isUndefined; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is a string or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is a string or not. + * If the given variable is a string, return true. + * @param {*} obj - Target for checking + * @returns {boolean} Is string? + * @memberof module:type + */ +function isString(obj) { + return typeof obj === 'string' || obj instanceof String; +} + +module.exports = isString; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Execute the provided callback once for each property of object which actually exist. + * @author NHN FE Development Lab + */ + + + +/** + * Execute the provided callback once for each property of object which actually exist. + * If the callback function returns false, the loop will be stopped. + * Callback function(iteratee) is invoked with three arguments: + * 1) The value of the property + * 2) The name of the property + * 3) The object being traversed + * @param {Object} obj The object that will be traversed + * @param {function} iteratee Callback function + * @param {Object} [context] Context(this) of callback function + * @memberof module:collection + * @example + * var forEachOwnProperties = require('tui-code-snippet/collection/forEachOwnProperties'); // node, commonjs + * + * var sum = 0; + * + * forEachOwnProperties({a:1,b:2,c:3}, function(value){ + * sum += value; + * }); + * alert(sum); // 6 + */ +function forEachOwnProperties(obj, iteratee, context) { + var key; + + context = context || null; + + for (key in obj) { + if (obj.hasOwnProperty(key)) { + if (iteratee.call(context, obj[key], key, obj) === false) { + break; + } + } + } +} + +module.exports = forEachOwnProperties; + + +/***/ }), +/* 11 */, +/* 12 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return isMac; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return sendHostName; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return includes; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return sanitizeLinkAttribute; }); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_request_sendHostname__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(43); +/* harmony import */ var tui_code_snippet_request_sendHostname__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_request_sendHostname__WEBPACK_IMPORTED_MODULE_1__); + + +var isMac = /Mac/.test(navigator.platform); +function sendHostName() { + tui_code_snippet_request_sendHostname__WEBPACK_IMPORTED_MODULE_1___default()('editor', 'UA-129966929-1'); +} +function includes(arr, targetItem) { + return arr.indexOf(targetItem) !== -1; +} +var availableLinkAttributes = ['rel', 'target', 'contenteditable', 'hreflang', 'type']; +/** + * sanitize attribute for link + * @param {object} attribute - attribute for link + * @returns {object} sanitized attribute + */ + +function sanitizeLinkAttribute(attribute) { + if (!attribute) { + return null; + } + + var linkAttribute = {}; + availableLinkAttributes.forEach(function (key) { + if (!tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_0___default()(attribute[key])) { + linkAttribute[key] = attribute[key]; + } + }); + return linkAttribute; +} + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check element match selector + * @author NHN FE Development Lab + */ + + + +var inArray = __webpack_require__(14); +var toArray = __webpack_require__(3); + +var elProto = Element.prototype; +var matchSelector = elProto.matches || + elProto.webkitMatchesSelector || + elProto.mozMatchesSelector || + elProto.msMatchesSelector || + function(selector) { + var doc = this.document || this.ownerDocument; + + return inArray(this, toArray(doc.querySelectorAll(selector))) > -1; + }; + +/** + * Check element match selector + * @param {HTMLElement} element - element to check + * @param {string} selector - selector to check + * @returns {boolean} is selector matched to element? + * @memberof module:domUtil + */ +function matches(element, selector) { + return matchSelector.call(element, selector); +} + +module.exports = matches; + + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* eslint-disable complexity */ +/** + * @fileoverview Returns the first index at which a given element can be found in the array. + * @author NHN FE Development Lab + */ + + + +var isArray = __webpack_require__(17); + +/** + * @module array + */ + +/** + * Returns the first index at which a given element can be found in the array + * from start index(default 0), or -1 if it is not present. + * It compares searchElement to elements of the Array using strict equality + * (the same method used by the ===, or triple-equals, operator). + * @param {*} searchElement Element to locate in the array + * @param {Array} array Array that will be traversed. + * @param {number} startIndex Start index in array for searching (default 0) + * @returns {number} the First index at which a given element, or -1 if it is not present + * @memberof module:array + * @example + * var inArray = require('tui-code-snippet/array/inArray'); // node, commonjs + * + * var arr = ['one', 'two', 'three', 'four']; + * var idx1 = inArray('one', arr, 3); // -1 + * var idx2 = inArray('one', arr); // 0 + */ +function inArray(searchElement, array, startIndex) { + var i; + var length; + startIndex = startIndex || 0; + + if (!isArray(array)) { + return -1; + } + + if (Array.prototype.indexOf) { + return Array.prototype.indexOf.call(array, searchElement, startIndex); + } + + length = array.length; + for (i = startIndex; startIndex >= 0 && i < length; i += 1) { + if (array[i] === searchElement) { + return i; + } + } + + return -1; +} + +module.exports = inArray; + + +/***/ }), +/* 15 */, +/* 16 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check element has specific css class + * @author NHN FE Development Lab + */ + + + +var inArray = __webpack_require__(14); +var getClass = __webpack_require__(33); + +/** + * Check element has specific css class + * @param {(HTMLElement|SVGElement)} element - target element + * @param {string} cssClass - css class + * @returns {boolean} + * @memberof module:domUtil + */ +function hasClass(element, cssClass) { + var origin; + + if (element.classList) { + return element.classList.contains(cssClass); + } + + origin = getClass(element).split(/\s+/); + + return inArray(cssClass, origin) > -1; +} + +module.exports = hasClass; + + +/***/ }), +/* 17 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is an instance of Array or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is an instance of Array or not. + * If the given variable is an instance of Array, return true. + * @param {*} obj - Target for checking + * @returns {boolean} Is array instance? + * @memberof module:type + */ +function isArray(obj) { + return obj instanceof Array; +} + +module.exports = isArray; + + +/***/ }), +/* 18 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return isNodeToBeCalculated; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return getAdditionalTopPos; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return getParentNodeObj; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return getCmRangeHeight; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return getNextEmptyLineHeight; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return getTotalOffsetTop; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return findAdjacentElementToScrollTop; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return getFallbackScrollTop; }); +/* harmony import */ var _utils_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); +/* harmony import */ var _utils_markdown__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); + + +var nestableTypes = ['list', 'blockQuote']; +var nestableTagNames = ['UL', 'OL', 'BLOCKQUOTE']; +var tableElementTagNames = ['TR', 'TH', 'TBODY', 'TD']; +function isNodeToBeCalculated(mdNode) { + return !Object(_utils_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(nestableTypes, mdNode.type); +} +function getAdditionalTopPos(scrollTop, offsetTop, currentNodeHeight, targetNodeHeight) { + var diff = (scrollTop - offsetTop) / currentNodeHeight; + return diff < 1 ? diff * targetNodeHeight : targetNodeHeight; +} +function getParentNodeObj(mdNode) { + var node = document.querySelector("[data-nodeid=\"" + mdNode.id + "\"]"); + + while (!node || Object(_utils_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(tableElementTagNames, mdNode.type) || Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_1__[/* isStyledTextNode */ "k"])(mdNode)) { + mdNode = mdNode.parent; + node = document.querySelector("[data-nodeid=\"" + mdNode.id + "\"]"); + } + + return getNonNestableNodeObj(getParentListItemObj(mdNode)); +} + +function getParentListItemObj(orgMdNode) { + var mdNode = orgMdNode; + + while (orgMdNode && orgMdNode !== 'document') { + if (orgMdNode.type === 'item') { + mdNode = orgMdNode; + break; + } + + orgMdNode = orgMdNode.parent; + } + + return { + mdNode: mdNode, + node: document.querySelector("[data-nodeid=\"" + mdNode.id + "\"]") + }; +} + +function getNonNestableNodeObj(_ref) { + var mdNode = _ref.mdNode, + node = _ref.node; + + while (Object(_utils_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(nestableTypes, mdNode.type) && mdNode.firstChild) { + mdNode = mdNode.firstChild; + node = node.firstElementChild; + } + + return { + mdNode: mdNode, + node: node + }; +} + +function getCmRangeHeight(mdNode, cm) { + var start = Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_1__[/* getMdStartLine */ "f"])(mdNode); + var end = Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_1__[/* getMdEndLine */ "d"])(mdNode); + var cmNodeHeight = cm.lineInfo(start - 1).handle.height; + var height = cm.heightAtLine(end, 'local') - cm.heightAtLine(start - 1, 'local'); + return height <= 0 ? cmNodeHeight : height + getNextEmptyLineHeight(cm, Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_1__[/* getMdEndLine */ "d"])(mdNode)); +} +function getNextEmptyLineHeight(cm, start, end) { + if (end === void 0) { + end = Number.MAX_VALUE; + } + + var lineInfo = cm.lineInfo(start); + + if (!lineInfo) { + return 0; + } + + var detailLineInfo = lineInfo.handle; + var height = 0; + + while (start <= end && !detailLineInfo.text.trim()) { + height += detailLineInfo.height; + start += 1; + detailLineInfo = cm.lineInfo(start).handle; + } + + return height; +} +function getTotalOffsetTop(el, root) { + var offsetTop = 0; + + while (el && el !== root) { + if (!Object(_utils_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(nestableTagNames, el.tagName)) { + offsetTop += el.offsetTop; + } + + if (el.offsetParent === root.offsetParent) { + break; + } + + el = el.parentElement; + } + + return offsetTop; +} +function findAdjacentElementToScrollTop(scrollTop, root) { + var el = root; + var prev = null; + + while (el) { + var _el = el, + firstElementChild = _el.firstElementChild; + + if (!firstElementChild) { + break; + } + + var lastSibling = findLastSiblingElementToScrollTop(firstElementChild, scrollTop, getTotalOffsetTop(el, root)); + prev = el; + el = lastSibling; + } + + var adjacentEl = el || prev; + return adjacentEl === root ? null : adjacentEl; +} + +function findLastSiblingElementToScrollTop(el, scrollTop, offsetTop) { + if (el && scrollTop > offsetTop + el.offsetTop) { + return findLastSiblingElementToScrollTop(el.nextElementSibling, scrollTop, offsetTop) || el; + } + + return null; +} + +function getFallbackScrollTop(scrollInfo) { + var latestScrollTop = scrollInfo.latestScrollTop, + scrollTop = scrollInfo.scrollTop, + targetScrollTop = scrollInfo.targetScrollTop, + sourceScrollTop = scrollInfo.sourceScrollTop; + + if (latestScrollTop === null) { + return targetScrollTop; + } + + return latestScrollTop < scrollTop ? Math.max(targetScrollTop, sourceScrollTop) : Math.min(targetScrollTop, sourceScrollTop); +} + +/***/ }), +/* 19 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Bind DOM events + * @author NHN FE Development Lab + */ + + + +var isString = __webpack_require__(9); +var forEach = __webpack_require__(26); + +var safeEvent = __webpack_require__(40); + +/** + * Bind DOM events. + * @param {HTMLElement} element - element to bind events + * @param {(string|object)} types - Space splitted events names or eventName:handler object + * @param {(function|object)} handler - handler function or context for handler method + * @param {object} [context] context - context for handler method. + * @memberof module:domEvent + * @example + * var div = document.querySelector('div'); + * + * // Bind one event to an element. + * on(div, 'click', toggle); + * + * // Bind multiple events with a same handler to multiple elements at once. + * // Use event names splitted by a space. + * on(div, 'mouseenter mouseleave', changeColor); + * + * // Bind multiple events with different handlers to an element at once. + * // Use an object which of key is an event name and value is a handler function. + * on(div, { + * keydown: highlight, + * keyup: dehighlight + * }); + * + * // Set a context for handler method. + * var name = 'global'; + * var repository = {name: 'CodeSnippet'}; + * on(div, 'drag', function() { + * console.log(this.name); + * }, repository); + * // Result when you drag a div: "CodeSnippet" + */ +function on(element, types, handler, context) { + if (isString(types)) { + forEach(types.split(/\s+/g), function(type) { + bindEvent(element, type, handler, context); + }); + + return; + } + + forEach(types, function(func, type) { + bindEvent(element, type, func, handler); + }); +} + +/** + * Bind DOM events + * @param {HTMLElement} element - element to bind events + * @param {string} type - events name + * @param {function} handler - handler function or context for handler method + * @param {object} [context] context - context for handler method. + * @private + */ +function bindEvent(element, type, handler, context) { + /** + * Event handler + * @param {Event} e - event object + */ + function eventHandler(e) { + handler.call(context || element, e || window.event); + } + + if ('addEventListener' in element) { + element.addEventListener(type, eventHandler); + } else if ('attachEvent' in element) { + element.attachEvent('on' + type, eventHandler); + } + memorizeHandler(element, type, handler, eventHandler); +} + +/** + * Memorize DOM event handler for unbinding. + * @param {HTMLElement} element - element to bind events + * @param {string} type - events name + * @param {function} handler - handler function that user passed at on() use + * @param {function} wrappedHandler - handler function that wrapped by domevent for implementing some features + * @private + */ +function memorizeHandler(element, type, handler, wrappedHandler) { + var events = safeEvent(element, type); + var existInEvents = false; + + forEach(events, function(obj) { + if (obj.handler === handler) { + existInEvents = true; + + return false; + } + + return true; + }); + + if (!existInEvents) { + events.push({ + handler: handler, + wrappedHandler: wrappedHandler + }); + } +} + +module.exports = on; + + +/***/ }), +/* 20 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Unbind DOM events + * @author NHN FE Development Lab + */ + + + +var isString = __webpack_require__(9); +var forEach = __webpack_require__(26); + +var safeEvent = __webpack_require__(40); + +/** + * Unbind DOM events + * If a handler function is not passed, remove all events of that type. + * @param {HTMLElement} element - element to unbind events + * @param {(string|object)} types - Space splitted events names or eventName:handler object + * @param {function} [handler] - handler function + * @memberof module:domEvent + * @example + * // Following the example of domEvent#on + * + * // Unbind one event from an element. + * off(div, 'click', toggle); + * + * // Unbind multiple events with a same handler from multiple elements at once. + * // Use event names splitted by a space. + * off(element, 'mouseenter mouseleave', changeColor); + * + * // Unbind multiple events with different handlers from an element at once. + * // Use an object which of key is an event name and value is a handler function. + * off(div, { + * keydown: highlight, + * keyup: dehighlight + * }); + * + * // Unbind events without handlers. + * off(div, 'drag'); + */ +function off(element, types, handler) { + if (isString(types)) { + forEach(types.split(/\s+/g), function(type) { + unbindEvent(element, type, handler); + }); + + return; + } + + forEach(types, function(func, type) { + unbindEvent(element, type, func); + }); +} + +/** + * Unbind DOM events + * If a handler function is not passed, remove all events of that type. + * @param {HTMLElement} element - element to unbind events + * @param {string} type - events name + * @param {function} [handler] - handler function + * @private + */ +function unbindEvent(element, type, handler) { + var events = safeEvent(element, type); + var index; + + if (!handler) { + forEach(events, function(item) { + removeHandler(element, type, item.wrappedHandler); + }); + events.splice(0, events.length); + } else { + forEach(events, function(item, idx) { + if (handler === item.handler) { + removeHandler(element, type, item.wrappedHandler); + index = idx; + + return false; + } + + return true; + }); + events.splice(index, 1); + } +} + +/** + * Remove an event handler + * @param {HTMLElement} element - An element to remove an event + * @param {string} type - event type + * @param {function} handler - event handler + * @private + */ +function removeHandler(element, type, handler) { + if ('removeEventListener' in element) { + element.removeEventListener(type, handler); + } else if ('detachEvent' in element) { + element.detachEvent('on' + type, handler); + } +} + +module.exports = off; + + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Execute the provided callback once for each element present in the array(or Array-like object) in ascending order. + * @author NHN FE Development Lab + */ + + + +/** + * Execute the provided callback once for each element present + * in the array(or Array-like object) in ascending order. + * If the callback function returns false, the loop will be stopped. + * Callback function(iteratee) is invoked with three arguments: + * 1) The value of the element + * 2) The index of the element + * 3) The array(or Array-like object) being traversed + * @param {Array|Arguments|NodeList} arr The array(or Array-like object) that will be traversed + * @param {function} iteratee Callback function + * @param {Object} [context] Context(this) of callback function + * @memberof module:collection + * @example + * var forEachArray = require('tui-code-snippet/collection/forEachArray'); // node, commonjs + * + * var sum = 0; + * + * forEachArray([1,2,3], function(value){ + * sum += value; + * }); + * alert(sum); // 6 + */ +function forEachArray(arr, iteratee, context) { + var index = 0; + var len = arr.length; + + context = context || null; + + for (; index < len; index += 1) { + if (iteratee.call(context, arr[index], index, arr) === false) { + break; + } + } +} + +module.exports = forEachArray; + + +/***/ }), +/* 22 */ +/***/ (function(module, exports) { + +!function(e,t){for(var r in t)e[r]=t[r]}(exports,function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="/dist",r(r.s=11)}([function(e,t,r){"use strict";r.r(t),r.d(t,"__extends",(function(){return i})),r.d(t,"__assign",(function(){return o})),r.d(t,"__rest",(function(){return a})),r.d(t,"__decorate",(function(){return s})),r.d(t,"__param",(function(){return l})),r.d(t,"__metadata",(function(){return u})),r.d(t,"__awaiter",(function(){return c})),r.d(t,"__generator",(function(){return p})),r.d(t,"__createBinding",(function(){return f})),r.d(t,"__exportStar",(function(){return d})),r.d(t,"__values",(function(){return h})),r.d(t,"__read",(function(){return g})),r.d(t,"__spread",(function(){return m})),r.d(t,"__spreadArrays",(function(){return v})),r.d(t,"__await",(function(){return b})),r.d(t,"__asyncGenerator",(function(){return y})),r.d(t,"__asyncDelegator",(function(){return C})),r.d(t,"__asyncValues",(function(){return x})),r.d(t,"__makeTemplateObject",(function(){return k})),r.d(t,"__importStar",(function(){return N})),r.d(t,"__importDefault",(function(){return w})),r.d(t,"__classPrivateFieldGet",(function(){return D})),r.d(t,"__classPrivateFieldSet",(function(){return L})); +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +var n=function(e,t){return(n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)};function i(e,t){function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}var o=function(){return(o=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=0;s--)(i=e[s])&&(a=(o<3?i(a):o>3?i(t,r,a):i(t,r))||a);return o>3&&a&&Object.defineProperty(t,r,a),a}function l(e,t){return function(r,n){t(r,n,e)}}function u(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function c(e,t,r,n){return new(r||(r=Promise))((function(i,o){function a(e){try{l(n.next(e))}catch(e){o(e)}}function s(e){try{l(n.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(a,s)}l((n=n.apply(e,t||[])).next())}))}function p(e,t){var r,n,i,o,a={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function s(o){return function(s){return function(o){if(r)throw new TypeError("Generator is already executing.");for(;a;)try{if(r=1,n&&(i=2&o[0]?n.return:o[0]?n.throw||((i=n.return)&&i.call(n),0):n.next)&&!(i=i.call(n,o[1])).done)return i;switch(n=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return a.label++,{value:o[1],done:!1};case 5:a.label++,n=o[1],o=[0];continue;case 7:o=a.ops.pop(),a.trys.pop();continue;default:if(!(i=a.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function g(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,i,o=r.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(n=o.next()).done;)a.push(n.value)}catch(e){i={error:e}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(i)throw i.error}}return a}function m(){for(var e=[],t=0;t1||s(e,t)}))})}function s(e,t){try{(r=i[e](t)).value instanceof b?Promise.resolve(r.value.v).then(l,u):c(o[0][2],r)}catch(e){c(o[0][3],e)}var r}function l(e){s("next",e)}function u(e){s("throw",e)}function c(e,t){e(t),o.shift(),o.length&&s(o[0][0],o[0][1])}}function C(e){var t,r;return t={},n("next"),n("throw",(function(e){throw e})),n("return"),t[Symbol.iterator]=function(){return this},t;function n(n,i){t[n]=e[n]?function(t){return(r=!r)?{value:b(e[n](t)),done:"return"===n}:i?i(t):t}:i}}function x(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,r=e[Symbol.asyncIterator];return r?r.call(e):(e=h(e),t={},n("next"),n("throw"),n("return"),t[Symbol.asyncIterator]=function(){return this},t);function n(r){t[r]=e[r]&&function(t){return new Promise((function(n,i){(function(e,t,r,n){Promise.resolve(n).then((function(t){e({value:t,done:r})}),t)})(n,i,(t=e[r](t)).done,t.value)}))}}}function k(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}function N(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t}function w(e){return e&&e.__esModule?e:{default:e}}function D(e,t){if(!t.has(e))throw new TypeError("attempted to get private field on non-instance");return t.get(e)}function L(e,t,r){if(!t.has(e))throw new TypeError("attempted to set private field on non-instance");return t.set(e,r),r}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.text=t.isRefDef=t.isTable=t.isList=t.isHeading=t.isHtmlBlock=t.isCodeBlock=t.createNode=t.RefDefNode=t.TableCellNode=t.TableNode=t.CodeNode=t.HtmlBlockNode=t.CodeBlockNode=t.LinkNode=t.HeadingNode=t.ListNode=t.BlockNode=t.Node=t.removeAllNode=t.removeNodeById=t.getNodeById=t.isContainer=void 0;var n=r(0),i=n.__importDefault(r(18));function o(e){switch(e.type){case"document":case"blockQuote":case"list":case"item":case"paragraph":case"heading":case"emph":case"strong":case"strike":case"link":case"image":case"table":case"tableHead":case"tableBody":case"tableRow":case"tableCell":case"tableDelimRow":return!0;default:return!1}}t.isContainer=o;var a=1,s={};t.getNodeById=function(e){return s[e]},t.removeNodeById=function(e){delete s[e]},t.removeAllNode=function(){s={}};var l=function(){function e(e,t){this.parent=null,this.prev=null,this.next=null,this.firstChild=null,this.lastChild=null,this.literal=null,this.id="document"===e?-1:a++,this.type=e,this.sourcepos=t,s[this.id]=this}return e.prototype.isContainer=function(){return o(this)},e.prototype.unlink=function(){this.prev?this.prev.next=this.next:this.parent&&(this.parent.firstChild=this.next),this.next?this.next.prev=this.prev:this.parent&&(this.parent.lastChild=this.prev),this.parent=null,this.next=null,this.prev=null},e.prototype.replaceWith=function(e){this.insertBefore(e),this.unlink()},e.prototype.insertAfter=function(e){e.unlink(),e.next=this.next,e.next&&(e.next.prev=e),e.prev=this,this.next=e,this.parent&&(e.parent=this.parent,e.next||(e.parent.lastChild=e))},e.prototype.insertBefore=function(e){e.unlink(),e.prev=this.prev,e.prev&&(e.prev.next=e),e.next=this,this.prev=e,e.parent=this.parent,e.prev||(e.parent.firstChild=e)},e.prototype.appendChild=function(e){e.unlink(),e.parent=this,this.lastChild?(this.lastChild.next=e,e.prev=this.lastChild,this.lastChild=e):(this.firstChild=e,this.lastChild=e)},e.prototype.prependChild=function(e){e.unlink(),e.parent=this,this.firstChild?(this.firstChild.prev=e,e.next=this.firstChild,this.firstChild=e):(this.firstChild=e,this.lastChild=e)},e.prototype.walker=function(){return new i.default(this)},e}();t.Node=l;var u=function(e){function t(t,r){var n=e.call(this,t,r)||this;return n.open=!0,n.lineOffsets=null,n.stringContent=null,n.lastLineBlank=!1,n.lastLineChecked=!1,n.customType=null,n.type=t,n}return n.__extends(t,e),t}(l);t.BlockNode=u;var c=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.listData=null,t}return n.__extends(t,e),t}(u);t.ListNode=c;var p=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.level=0,t.headingType="atx",t}return n.__extends(t,e),t}(u);t.HeadingNode=p;var f=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.destination=null,t.title=null,t.extendedAutolink=!1,t}return n.__extends(t,e),t}(l);t.LinkNode=f;var d=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.isFenced=!1,t.fenceChar=null,t.fenceLength=0,t.fenceOffset=-1,t.info=null,t.infoPadding=0,t}return n.__extends(t,e),t}(u);t.CodeBlockNode=d;var h=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.htmlBlockType=-1,t}return n.__extends(t,e),t}(u);t.HtmlBlockNode=h;var g=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.tickCount=0,t}return n.__extends(t,e),t}(l);t.CodeNode=g;var m=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.columns=[],t}return n.__extends(t,e),t}(u);t.TableNode=m;var v=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.startIdx=0,t.endIdx=0,t.paddingLeft=0,t.paddingRight=0,t.ignored=!1,t}return n.__extends(t,e),t}(u);t.TableCellNode=v;var b=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.title="",t.dest="",t.label="",t}return n.__extends(t,e),t}(u);function y(e,t){switch(e){case"heading":return new p(e,t);case"list":case"item":return new c(e,t);case"link":case"image":return new f(e,t);case"codeBlock":return new d(e,t);case"htmlBlock":return new h(e,t);case"table":return new m(e,t);case"tableCell":return new v(e,t);case"document":case"paragraph":case"blockQuote":case"thematicBreak":case"tableRow":case"tableBody":case"tableHead":return new u(e,t);case"code":return new g(e,t);case"refDef":return new b(e,t);default:return new l(e,t)}}t.RefDefNode=b,t.createNode=y,t.isCodeBlock=function(e){return"codeBlock"===e.type},t.isHtmlBlock=function(e){return"htmlBlock"===e.type},t.isHeading=function(e){return"heading"===e.type},t.isList=function(e){return"list"===e.type},t.isTable=function(e){return"table"===e.type},t.isRefDef=function(e){return"refDef"===e.type},t.text=function(e,t){var r=y("text",t);return r.literal=e,r}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isEmpty=t.last=t.repeat=t.escapeXml=t.normalizeURI=t.unescapeString=t.ESCAPABLE=t.ENTITY=void 0;var n=r(0).__importDefault(r(12)),i=r(8);t.ENTITY="&(?:#x[a-f0-9]{1,6}|#[0-9]{1,7}|[a-z][a-z0-9]{1,31});";var o=/[\\&]/;t.ESCAPABLE="[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]";var a=new RegExp("\\\\"+t.ESCAPABLE+"|"+t.ENTITY,"gi"),s=new RegExp('[&<>"]',"g"),l=function(e){return 92===e.charCodeAt(0)?e.charAt(1):i.decodeHTML(e)};function u(e){switch(e){case"&":return"&";case"<":return"<";case">":return">";case'"':return""";default:return e}}t.unescapeString=function(e){return o.test(e)?e.replace(a,l):e},t.normalizeURI=function(e){try{return n.default(e)}catch(t){return e}},t.escapeXml=function(e){return s.test(e)?e.replace(s,u):e},t.repeat=function(e,t){for(var r=[],n=0;nt&&(t+=1),this.root.sourcepos[1]=[t+1,e[t].length]},e.prototype.replaceRangeNodes=function(e,t,r){e?(a.insertNodesBefore(e,r),a.removeNextUntil(e,t),[e.id,t.id].forEach((function(e){return o.removeNodeById(e)})),e.unlink()):t?(a.insertNodesBefore(t,r),o.removeNodeById(t.id),t.unlink()):a.prependChildNodes(this.root,r)},e.prototype.getNodeRange=function(e,t){var r=a.findChildNodeAtLine(this.root,e[0]),n=a.findChildNodeAtLine(this.root,t[0]);return n&&n.next&&t[0]+1===n.next.sourcepos[0][0]&&(n=n.next),a.getRangeForCustomType(r,n)},e.prototype.trigger=function(e,t){this.eventHandlerMap[e].forEach((function(e){e(t)}))},e.prototype.extendEndLine=function(e){for(;""===this.lineTexts[e];)e+=1;return e},e.prototype.parseRange=function(e,t,r,n){var i;e&&e.prev&&(o.isList(e.prev)&&function(e){var t=e.match(/^[ \t]+/);if(t&&(t[0].length>=2||/\t/.test(t[0])))return!0;var r=t?e.slice(t.length):e;return s.reBulletListMarker.test(r)||s.reOrderedListMarker.test(r)}(this.lineTexts[r-1])||o.isTable(e.prev)&&(i=this.lineTexts[r-1],!u.isBlank(i)&&-1!==i.indexOf("|")))&&(r=(e=e.prev).sourcepos[0][0]);for(var l=this.lineTexts.slice(r-1,n),c=this.parser.partialParseStart(r,l),p=t?t.next:this.root.firstChild,f=c.lastChild,d=f&&o.isCodeBlock(f),h=f&&o.isList(f);d&&p||h&&p&&("list"===p.type||p.sourcepos[0][1]>=2);){var g=this.extendEndLine(p.sourcepos[1][0]);this.parser.partialParseExtends(this.lineTexts.slice(n,g)),e||(e=t),t=p,n=g,p=p.next}return this.parser.partialParseFinish(),{newNodes:a.getChildNodes(c),extStartNode:e,extEndNode:t}},e.prototype.getRemovedNodeRange=function(e,t){return!e||e&&o.isRefDef(e)||t&&o.isRefDef(t)?null:{id:[e.id,t.id],line:[e.sourcepos[0][0]-1,t.sourcepos[1][0]-1]}},e.prototype.markDeletedRefMap=function(e,t){var r=this;if(!l.isEmptyObj(this.refMap)){var n=function(e){if(o.isRefDef(e)){var t=r.refMap[e.label];t&&e.id===t.id&&(t.unlinked=!0)}};e&&a.invokeNextUntil(n,e.parent,t),t&&a.invokeNextUntil(n,t)}},e.prototype.replaceWithNewRefDefState=function(e){var t=this;if(!l.isEmptyObj(this.refMap)){var r=function(e){if(o.isRefDef(e)){var r=e.label,n=t.refMap[r];n&&!n.unlinked||(t.refMap[r]=p(e))}};e.forEach((function(e){a.invokeNextUntil(r,e)}))}},e.prototype.replaceWithRefDefCandidate=function(){var e=this;l.isEmptyObj(this.refDefCandidateMap)||l.iterateObject(this.refDefCandidateMap,(function(t,r){var n=r.label,i=r.sourcepos,o=e.refMap[n];(!o||o.unlinked||o.sourcepos[0][0]>i[0][0])&&(e.refMap[n]=p(r))}))},e.prototype.getRangeWithRefDef=function(e,t,r,n,i){if(this.referenceDefinition&&!l.isEmptyObj(this.refMap)){var s=a.findChildNodeAtLine(this.root,e-1),u=a.findChildNodeAtLine(this.root,t+1);s&&o.isRefDef(s)&&s!==r&&s!==n&&(e=(r=s).sourcepos[0][0]),u&&o.isRefDef(u)&&u!==r&&u!==n&&(n=u,t=this.extendEndLine(n.sourcepos[1][0]+i))}return[r,n,e,t]},e.prototype.parseWithFrontMatter=function(e,t,r){void 0===r&&(r=0);var i=n.__spreadArrays(this.lineTexts),o=c.getFrontMatterPos(this.lineTexts),a=o[0],s=o[1];a>-1&&s>-1&&(this.lineTexts[a]=c.frontMatterOpen,this.lineTexts[s]=c.frontMatterClose,a>=t[0]-1&&(t[0]=s+1),a<=e[0]-1&&s>=t[0]-1&&(e[0]=a+1,t[0]=s+1));var l=this.parse(e,t,r);return this.lineTexts=i,l},e.prototype.parse=function(e,t,r){void 0===r&&(r=0);var n=this.getNodeRange(e,t),i=n[0],o=n[1],a=i?Math.min(i.sourcepos[0][0],e[0]):e[0],s=this.extendEndLine((o?Math.max(o.sourcepos[1][0],t[0]):t[0])+r),l=this.parseRange.apply(this,this.getRangeWithRefDef(a,s,i,o,r)),u=l.newNodes,c=l.extStartNode,p=l.extEndNode,f=this.getRemovedNodeRange(c,p),d=p?p.next:this.root.firstChild;return this.referenceDefinition?(this.markDeletedRefMap(c,p),this.replaceRangeNodes(c,p,u),this.replaceWithNewRefDefState(u)):this.replaceRangeNodes(c,p,u),{nodes:u,removedNodeRange:f,nextNode:d}},e.prototype.parseRefLink=function(){var e=this,t=[];return l.isEmptyObj(this.refMap)||l.iterateObject(this.refMap,(function(r,n){n.unlinked&&delete e.refMap[r],l.iterateObject(e.refLinkCandidateMap,(function(n,i){var o=i.node;i.refLabel===r&&t.push(e.parse(o.sourcepos[0],o.sourcepos[1]))}))})),t},e.prototype.removeUnlinkedCandidate=function(){l.isEmptyObj(this.refDefCandidateMap)||[this.refLinkCandidateMap,this.refDefCandidateMap].forEach((function(e){l.iterateObject(e,(function(t){a.isUnlinked(t)&&delete e[t]}))}))},e.prototype.editMarkdown=function(e,t,r){var n=this.updateLineTexts(e,t,r),i=this.frontMatter?this.parseWithFrontMatter(e,t,n):this.parse(e,t,n),o=l.omit(i,"nextNode");a.updateNextLineNumbers(i.nextNode,n),this.updateRootNodeState();var s=[o];return this.referenceDefinition&&(this.removeUnlinkedCandidate(),this.replaceWithRefDefCandidate(),s=s.concat(this.parseRefLink())),this.trigger("change",s),s},e.prototype.getLineTexts=function(){return this.lineTexts},e.prototype.getRootNode=function(){return this.root},e.prototype.findNodeAtPosition=function(e){var t=a.findNodeAtPosition(this.root,e);return t&&t!==this.root?t:null},e.prototype.findFirstNodeAtLine=function(e){return a.findFirstNodeAtLine(this.root,e)},e.prototype.on=function(e,t){this.eventHandlerMap[e].push(t)},e.prototype.off=function(e,t){var r=this.eventHandlerMap[e],n=r.indexOf(t);r.splice(n,1)},e.prototype.findNodeById=function(e){return a.findNodeById(e)},e.prototype.removeAllNode=function(){o.removeAllNode()},e}();t.ToastMark=f},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getFrontMatterPos=t.replaceFrontMatter=t.frontMatterClose=t.frontMatterOpen=void 0,t.frontMatterOpen="{:f",t.frontMatterClose="f:}";var n=/^---$/,i=/^---$([\s\S]*)^---$/m;t.replaceFrontMatter=function(e){var r=e.trim();return/^---/.test(r)&&function(e){return i.test(e)}(r)?e.replace(i,t.frontMatterOpen+"$1"+t.frontMatterClose):e},t.getFrontMatterPos=function(e){for(var t=-1,r=-1,i=0;i0)break;n.test(o)&&(t<0?t=i:r=i)}return[t,r]}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Parser=void 0;var n=r(0),i=r(2),o=r(1),a=r(19),s=r(22),l=r(4),u=r(10),c=r(3),p=r(6),f=r(26),d=[/./,/<\/(?:script|pre|style)>/i,/-->/,/\?>/,/>/,/\]\]>/],h=/^[#`~*+_=<>0-9-]/,g=/\r\n|\n|\r/;function m(){return o.createNode("document",[[1,1],[0,0]])}var v={smart:!1,tagFilter:!1,extendedAutolinks:!1,disallowedHtmlBlockTags:[],referenceDefinition:!1,disallowDeepHeading:!1,customParser:null,frontMatter:!1},b=function(){function e(e){this.options=n.__assign(n.__assign({},v),e),this.doc=m(),this.tip=this.doc,this.oldtip=this.doc,this.lineNumber=0,this.offset=0,this.column=0,this.nextNonspace=0,this.nextNonspaceColumn=0,this.indent=0,this.currentLine="",this.indented=!1,this.blank=!1,this.partiallyConsumedTab=!1,this.allClosed=!0,this.lastMatchedContainer=this.doc,this.refMap={},this.refLinkCandidateMap={},this.refDefCandidateMap={},this.lastLineLength=0,this.options.frontMatter&&(this.options.customParser=n.__assign(n.__assign({},f.frontMatterParser),this.options.customParser)),this.inlineParser=new a.InlineParser(this.options)}return e.prototype.advanceOffset=function(e,t){void 0===t&&(t=!1);for(var r,n,i,o=this.currentLine;e>0&&(i=o[this.offset]);)"\t"===i?(r=4-this.column%4,t?(this.partiallyConsumedTab=r>e,n=r>e?e:r,this.column+=n,this.offset+=this.partiallyConsumedTab?0:1,e-=n):(this.partiallyConsumedTab=!1,this.column+=r,this.offset+=1,e-=1)):(this.partiallyConsumedTab=!1,this.offset+=1,this.column+=1,e-=1)},e.prototype.advanceNextNonspace=function(){this.offset=this.nextNonspace,this.column=this.nextNonspaceColumn,this.partiallyConsumedTab=!1},e.prototype.findNextNonspace=function(){for(var e,t=this.currentLine,r=this.offset,n=this.column;""!==(e=t.charAt(r));)if(" "===e)r++,n++;else{if("\t"!==e)break;r++,n+=4-n%4}this.blank="\n"===e||"\r"===e||""===e,this.nextNonspace=r,this.nextNonspaceColumn=n,this.indent=this.nextNonspaceColumn-this.column,this.indented=this.indent>=l.CODE_INDENT},e.prototype.addLine=function(){if(this.partiallyConsumedTab){this.offset+=1;var e=4-this.column%4;this.tip.stringContent+=i.repeat(" ",e)}this.tip.lineOffsets?this.tip.lineOffsets.push(this.offset):this.tip.lineOffsets=[this.offset],this.tip.stringContent+=this.currentLine.slice(this.offset)+"\n"},e.prototype.addChild=function(e,t){for(;!s.blockHandlers[this.tip.type].canContain(e);)this.finalize(this.tip,this.lineNumber-1);var r=t+1,n=o.createNode(e,[[this.lineNumber,r],[0,0]]);return n.stringContent="",this.tip.appendChild(n),this.tip=n,n},e.prototype.closeUnmatchedBlocks=function(){if(!this.allClosed){for(;this.oldtip!==this.lastMatchedContainer;){var e=this.oldtip.parent;this.finalize(this.oldtip,this.lineNumber-1),this.oldtip=e}this.allClosed=!0}},e.prototype.finalize=function(e,t){var r=e.parent;e.open=!1,e.sourcepos[1]=[t,this.lastLineLength],s.blockHandlers[e.type].finalize(this,e),this.tip=r},e.prototype.processInlines=function(e){var t,r=this.options.customParser,n=e.walker();for(this.inlineParser.refMap=this.refMap,this.inlineParser.refLinkCandidateMap=this.refLinkCandidateMap,this.inlineParser.refDefCandidateMap=this.refDefCandidateMap,this.inlineParser.options=this.options;t=n.next();){var i=t.node,o=t.entering,a=i.type;r&&r[a]&&r[a](i,{entering:o,options:this.options}),o||"paragraph"!==a&&"heading"!==a&&("tableCell"!==a||i.ignored)||this.inlineParser.parse(i)}},e.prototype.incorporateLine=function(e){var t=this.doc;this.oldtip=this.tip,this.offset=0,this.column=0,this.blank=!1,this.partiallyConsumedTab=!1,this.lineNumber+=1,-1!==e.indexOf("\0")&&(e=e.replace(/\0/g,"�")),this.currentLine=e;for(var r,n=!0;(r=t.lastChild)&&r.open;){switch(t=r,this.findNextNonspace(),s.blockHandlers[t.type].continue(this,t)){case 0:break;case 1:n=!1;break;case 2:return void(this.lastLineLength=e.length);default:throw new Error("continue returned illegal value, must be 0, 1, or 2")}if(!n){t=t.parent;break}}this.allClosed=t===this.oldtip,this.lastMatchedContainer=t;for(var i="paragraph"!==t.type&&s.blockHandlers[t.type].acceptsLines,a=u.blockStarts.length;!i;){if(this.findNextNonspace(),"table"!==t.type&&"tableBody"!==t.type&&"paragraph"!==t.type&&!this.indented&&!h.test(e.slice(this.nextNonspace))){this.advanceNextNonspace();break}for(var l=0;l=1&&t.htmlBlockType<=5&&d[t.htmlBlockType].test(this.currentLine.slice(this.offset))&&(this.lastLineLength=e.length,this.finalize(t,this.lineNumber))):this.offset`\\x00-\\x20]+|'[^']*'|\"[^\"]*\"))?)*\\s*/?>",t.CLOSETAG="]";var n="(?:"+t.OPENTAG+"|"+t.CLOSETAG+"|\x3c!----\x3e|\x3c!--(?:-?[^>-])(?:-?[^-])*--\x3e|[<][?].*?[?][>]|]*>|)";t.reHtmlTag=new RegExp("^"+n,"i")},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.blockStarts=t.reOrderedListMarker=t.reBulletListMarker=void 0;var n=r(1),i=r(9),o=r(4),a=r(25),s=/^`{3,}(?!.*`)|^~{3,}/,l=[/./,/^<(?:script|pre|style)(?:\s|>|$)/i,/^/g, ''); + root.innerHTML = html; + } else { + root.appendChild(html); + } + + removeUnnecessaryTags(root); + leaveOnlyWhitelistAttribute(root); + return _utils_dom__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"].finalizeHtml(root, needHtmlText); +} +/** + * Removes unnecessary tags. + * @param {HTMLElement} html - root element + * @private + */ + + +function removeUnnecessaryTags(html) { + var removedTags = _utils_dom__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"].findAll(html, 'script, iframe, textarea, form, button, select, input, meta, style, link, title, embed, object, details, summary'); + removedTags.forEach(function (node) { + _utils_dom__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"].remove(node); + }); +} +/** + * Checks whether the attribute and value that causing XSS or not. + * @param {string} attrName - name of attribute + * @param {string} attrValue - value of attirbute + * @param {boolean} state + * @private + */ + + +function isXSSAttribute(attrName, attrValue) { + return attrName.match(XSS_ATTR_RX) && attrValue.match(XSS_VALUE_RX); +} +/** + * Removes attributes of blacklist from node. + * @param {HTMLElement} node - node to remove attributes + * @param {NamedNodeMap} blacklistAttrs - attributes of blacklist + * @private + */ + + +function removeBlacklistAttributes(node, blacklistAttrs) { + tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(blacklistAttrs).forEach(function (_ref) { + var name = _ref.name; + + if (ON_EVENT_RX.test(name)) { + node[name] = null; + } + + if (node.getAttribute(name)) { + node.removeAttribute(name); + } + }); +} +/** + * Leaves only white list attributes. + * @param {HTMLElement} html - root element + * @private + */ + + +function leaveOnlyWhitelistAttribute(html) { + _utils_dom__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"].findAll(html, '*').forEach(function (node) { + var attributes = node.attributes; + var blacklist = tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(attributes).filter(function (attr) { + var name = attr.name, + value = attr.value; + var htmlAttr = name.match(HTML_ATTR_LIST_RX); + var svgAttr = name.match(SVG_ATTR_LIST_RX); + var xssAttr = htmlAttr && isXSSAttribute(name, value); + return !htmlAttr && !svgAttr || xssAttr; + }); + removeBlacklistAttributes(node, blacklist); + }); +} + +/* harmony default export */ __webpack_exports__["a"] = (htmlSanitizer); + +/***/ }), +/* 26 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Execute the provided callback once for each property of object(or element of array) which actually exist. + * @author NHN FE Development Lab + */ + + + +var isArray = __webpack_require__(17); +var forEachArray = __webpack_require__(21); +var forEachOwnProperties = __webpack_require__(10); + +/** + * @module collection + */ + +/** + * Execute the provided callback once for each property of object(or element of array) which actually exist. + * If the object is Array-like object(ex-arguments object), It needs to transform to Array.(see 'ex2' of example). + * If the callback function returns false, the loop will be stopped. + * Callback function(iteratee) is invoked with three arguments: + * 1) The value of the property(or The value of the element) + * 2) The name of the property(or The index of the element) + * 3) The object being traversed + * @param {Object} obj The object that will be traversed + * @param {function} iteratee Callback function + * @param {Object} [context] Context(this) of callback function + * @memberof module:collection + * @example + * var forEach = require('tui-code-snippet/collection/forEach'); // node, commonjs + * + * var sum = 0; + * + * forEach([1,2,3], function(value){ + * sum += value; + * }); + * alert(sum); // 6 + * + * // In case of Array-like object + * var array = Array.prototype.slice.call(arrayLike); // change to array + * forEach(array, function(value){ + * sum += value; + * }); + */ +function forEach(obj, iteratee, context) { + if (isArray(obj)) { + forEachArray(obj, iteratee, context); + } else { + forEachOwnProperties(obj, iteratee, context); + } +} + +module.exports = forEach; + + +/***/ }), +/* 27 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is a function or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is a function or not. + * If the given variable is a function, return true. + * @param {*} obj - Target for checking + * @returns {boolean} Is function? + * @memberof module:type + */ +function isFunction(obj) { + return obj instanceof Function; +} + +module.exports = isFunction; + + +/***/ }), +/* 28 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is existing or not. + * @author NHN FE Development Lab + */ + + + +var isUndefined = __webpack_require__(8); +var isNull = __webpack_require__(48); + +/** + * Check whether the given variable is existing or not. + * If the given variable is not null and not undefined, returns true. + * @param {*} param - Target for checking + * @returns {boolean} Is existy? + * @memberof module:type + * @example + * var isExisty = require('tui-code-snippet/type/isExisty'); // node, commonjs + * + * isExisty(''); //true + * isExisty(0); //true + * isExisty([]); //true + * isExisty({}); //true + * isExisty(null); //false + * isExisty(undefined); //false +*/ +function isExisty(param) { + return !isUndefined(param) && !isNull(param); +} + +module.exports = isExisty; + + +/***/ }), +/* 29 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return getHTMLRenderConvertors; }); +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +var baseConvertors = { + paragraph: function paragraph(node, _ref) { + var entering = _ref.entering, + origin = _ref.origin, + options = _ref.options; + var nodeId = options.nodeId, + _options$customProp = options.customProp, + customProp = _options$customProp === void 0 ? {} : _options$customProp; + var showFrontMatter = customProp.showFrontMatter && node.customType; // prevent paragraph from being removed when it's child of tight list item + // to show highlight style in live-preview mode + + if (nodeId && !node.customType || showFrontMatter) { + return { + type: entering ? 'openTag' : 'closeTag', + outerNewLine: true, + tagName: 'p' + }; + } + + return origin(); + }, + softbreak: function softbreak(node) { + var isPrevNodeHTML = node.prev && node.prev.type === 'htmlInline'; + var isPrevBR = isPrevNodeHTML && /
/.test(node.prev.literal); + var content = isPrevBR ? '\n' : '
\n'; + return { + type: 'html', + content: content + }; + }, + item: function item(node, _ref2) { + var entering = _ref2.entering; + + if (entering) { + var attributes = {}; + var classNames = []; + + if (node.listData.task) { + attributes['data-te-task'] = ''; + classNames.push('task-list-item'); + + if (node.listData.checked) { + classNames.push('checked'); + } + } + + return { + type: 'openTag', + tagName: 'li', + classNames: classNames, + attributes: attributes, + outerNewLine: true + }; + } + + return { + type: 'closeTag', + tagName: 'li', + outerNewLine: true + }; + }, + code: function code(node) { + var attributes = { + 'data-backticks': node.tickCount + }; + return [{ + type: 'openTag', + tagName: 'code', + attributes: attributes + }, { + type: 'text', + content: node.literal + }, { + type: 'closeTag', + tagName: 'code' + }]; + }, + codeBlock: function codeBlock(node) { + var infoWords = node.info ? node.info.split(/\s+/) : []; + var preClasses = []; + var codeAttrs = {}; + + if (node.fenceLength > 3) { + codeAttrs['data-backticks'] = node.fenceLength; + } + + if (infoWords.length > 0 && infoWords[0].length > 0) { + var lang = infoWords[0]; + preClasses.push("lang-" + lang); + codeAttrs['data-language'] = lang; + } + + return [{ + type: 'openTag', + tagName: 'pre', + classNames: preClasses + }, { + type: 'openTag', + tagName: 'code', + attributes: codeAttrs + }, { + type: 'text', + content: node.literal + }, { + type: 'closeTag', + tagName: 'code' + }, { + type: 'closeTag', + tagName: 'pre' + }]; + } +}; +function getHTMLRenderConvertors(linkAttribute, customConvertors) { + var convertors = _extends({}, baseConvertors); + + if (linkAttribute) { + convertors.link = function (_, _ref3) { + var entering = _ref3.entering, + origin = _ref3.origin; + var result = origin(); + + if (entering) { + result.attributes = _extends({}, result.attributes, linkAttribute); + } + + return result; + }; + } + + if (customConvertors) { + Object.keys(customConvertors).forEach(function (nodeType) { + var orgConvertor = convertors[nodeType]; + var customConvertor = customConvertors[nodeType]; + + if (orgConvertor) { + convertors[nodeType] = function (node, context) { + var newContext = _extends({}, context); + + newContext.origin = function () { + return orgConvertor(node, context); + }; + + return customConvertor(node, newContext); + }; + } else { + convertors[nodeType] = customConvertor; + } + }); + } + + return convertors; +} + +/***/ }), +/* 30 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export CodeBlockManager */ +/** + * @fileoverview Implements CodeBlockManager + * @author NHN FE Development Lab + */ + +/** + * Class Code Block Manager + */ +var CodeBlockManager = /*#__PURE__*/function () { + function CodeBlockManager() { + this._replacers = {}; + } + /** + * Set replacer for code block + * @param {string} language - code block language + * @param {function} replacer - replacer function to code block element + */ + + + var _proto = CodeBlockManager.prototype; + + _proto.setReplacer = function setReplacer(language, replacer) { + language = language.toLowerCase(); + this._replacers[language] = replacer; + } + /** + * get replacer for code block + * @param {string} language - code block type + * @returns {function} - replacer function + */ + ; + + _proto.getReplacer = function getReplacer(language) { + return this._replacers[language]; + } + /** + * Create code block html. + * @param {string} language - code block language + * @param {string} codeText - code text + * @returns {string} + */ + ; + + _proto.createCodeBlockHtml = function createCodeBlockHtml(language, codeText) { + language = language.toLowerCase(); + var replacer = this.getReplacer(language); + + if (replacer) { + return replacer(codeText, language); + } + + return escape(codeText, false); + }; + + return CodeBlockManager; +}(); +/** + * escape code from markdown-it + * @param {string} html HTML string + * @param {string} encode Boolean value of whether encode or not + * @returns {string} + * @ignore + */ + + +function escape(html, encode) { + return html.replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, '''); +} + + +/* harmony default export */ __webpack_exports__["a"] = (new CodeBlockManager()); + +/***/ }), +/* 31 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return invokePlugins; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return getPluginInfo; }); +/* harmony import */ var tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(17); +/* harmony import */ var tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_type_isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(27); +/* harmony import */ var tui_code_snippet_type_isFunction__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isFunction__WEBPACK_IMPORTED_MODULE_1__); +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + + + +/** + * Invoke plugins + * @param {Array.} plugins - list of plugin function only or + * plugin function with options + * @param {Editor|Viewer} editor - editor or viewer instance + */ + +function invokePlugins(plugins, editor) { + plugins.forEach(function (plugin) { + if (tui_code_snippet_type_isFunction__WEBPACK_IMPORTED_MODULE_1___default()(plugin)) { + plugin(editor); + } else if (tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0___default()(plugin)) { + var pluginFn = plugin[0], + _plugin$ = plugin[1], + options = _plugin$ === void 0 ? {} : _plugin$; + pluginFn(editor, options); + } + }); +} +/** + * Get plugin info + * @param {Array.} plugins - list of plugin function only or + * plugin function with options + * @returns {Object} - plugin info + */ + +function getPluginInfo(plugins) { + if (!plugins) { + return {}; + } + + return plugins.reduce(function (acc, plugin) { + var pluginInfo = tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0___default()(plugin) ? plugin[0] : plugin; + + if (!tui_code_snippet_type_isFunction__WEBPACK_IMPORTED_MODULE_1___default()(pluginInfo)) { + var renderer = pluginInfo.renderer, + parser = pluginInfo.parser, + pluginFn = pluginInfo.pluginFn; + plugin = tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0___default()(plugin) ? [pluginFn, plugin[1]] : pluginFn; + + if (renderer) { + acc.renderer = _extends({}, acc.renderer, renderer); + } + + if (parser) { + acc.parser = _extends({}, acc.parser, parser); + } + } + + acc.plugins.push(plugin); + return acc; + }, { + plugins: [], + renderer: {}, + parser: {} + }); +} + +/***/ }), +/* 32 */ +/***/ (function(module, exports, __webpack_require__) { + +/*! + * to-mark + * @version 1.0.1 | Tue Nov 24 2020 + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(true) + module.exports = factory(); + else {} +})(window, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +// ESM COMPAT FLAG +__webpack_require__.r(__webpack_exports__); + +// CONCATENATED MODULE: ./src/domRunner.js +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview Implements DomRunner + * @author NHN Ent. FE Development Lab + */ +var NODE = { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3 +}; +/** + * DomRunner + * @param {HTMLElement} node A root node that it has nodes to iterate(not iterate itself and its any siblings) + * @class + */ + +var DomRunner = /*#__PURE__*/function () { + function DomRunner(node) { + this._normalizeTextChildren(node); + + this._root = node; + this._current = node; + } + /** + * Iterate next node + * @returns {HTMLElement} next node + */ + + + var _proto = DomRunner.prototype; + + _proto.next = function next() { + var current = this._current; + var node; + + if (this._current) { + node = this._getNextNode(current); + + while (this._isNeedNextSearch(node, current)) { + current = current.parentNode; + node = current.nextSibling; + } + + this._current = node; + } + + return this._current; + } + /** + * Return current node + * @returns {HTMLElement} current node + */ + ; + + _proto.getNode = function getNode() { + this._normalizeTextChildren(this._current); + + return this._current; + }; + + _proto._normalizeTextChildren = function _normalizeTextChildren(node) { + if (!node || node.childNodes.length < 2) { + return; + } + + var childNode = node.firstChild; + var nextNode; + + while (childNode.nextSibling) { + nextNode = childNode.nextSibling; + + if (childNode.nodeType === NODE.TEXT_NODE && nextNode.nodeType === NODE.TEXT_NODE) { + childNode.nodeValue += nextNode.nodeValue; + node.removeChild(nextNode); + } else { + childNode = nextNode; + } + } + } + /** + * Get current node's text content + * @returns {string} text + */ + ; + + _proto.getNodeText = function getNodeText() { + var node = this.getNode(); + var text; + + if (node.nodeType === NODE.TEXT_NODE) { + text = node.nodeValue; + } else { + text = node.textContent || node.innerText; + } + + return text; + } + /** + * Check if there is next node to iterate + * @private + * @param {HTMLElement} node next node + * @param {HTMLElement} current next node + * @returns {boolean} result + */ + ; + + _proto._isNeedNextSearch = function _isNeedNextSearch(node, current) { + return !node && current !== this._root && current.parentNode !== this._root; + } + /** + * Return available next node + * @private + * @param {HTMLElement} current current node + * @returns {node} next node + */ + ; + + _proto._getNextNode = function _getNextNode(current) { + return current.firstChild || current.nextSibling; + }; + + return DomRunner; +}(); + +_defineProperty(DomRunner, "NODE_TYPE", NODE); + + +// CONCATENATED MODULE: ./src/toDom.js +/** + * @fileoverview Implements toDom + * @author NHN Ent. FE Development Lab + */ +var FIND_FIRST_LAST_SPACE_OR_RETURN_OR_TAB_RX = /^[\s\r\n\t]+|[\s\r\n\t]+$/g; +var FIND_RETURN_OR_TAB_BETWEEN_TAGS_RX = />[\r\n\t]+[ ]+<'); // remove spaces more than 1(if need more space, must use  ) + + html = html.replace(FIND_WHOLE_SPACE_MORE_THAN_ONE_BETWEEN_TAGS_RX, '> <'); + return html; +} + +toDom.preProcess = preProcess; +// CONCATENATED MODULE: ./src/renderer.js +function renderer_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview Implements Renderer + * @author NHN Ent. FE Development Lab + */ +var FIND_LEAD_SPACE_RX = /^\u0020/; +var FIND_TRAIL_SPACE_RX = /.+\u0020$/; +var FIND_SPACE_RETURN_TAB_RX = /[\n\s\t]+/g; +var FIND_CHAR_TO_TRIM_RX = /^[\u0020\r\n\t]+|[\u0020\r\n\t]+$/g; // find first and last characters for trim + +var FIND_SPACE_MORE_THAN_ONE_RX = /[\u0020]+/g; // find space more than one + +var FIND_CHAR_TO_ESCAPE_RX = /[>(){}[\]+-.!#|]/g; // find characters that need escape + +var FIND_CHAR_TO_ESCAPE_IN_LINK_RX = /[[\]]/g; // find characters to be escaped in links or images + +var FIND_MARKDOWN_IMAGE_SYNTAX_RX = /!\[.*\]\(.*\)/g; // find markdown image syntax + +var TEXT_NODE = 3; +/** + * Iterate properties of object + * from https://github.com/nhnent/fe.code-snippet/blob/master/src/collection.js + * @param {object} obj object to iterate + * @param {function} iteratee callback function + * @param {*} [context] context of callback + */ + +function forEachOwnProperties(obj, iteratee, context) { + var key; + context = context || null; + + for (key in obj) { + if (obj.hasOwnProperty(key)) { + if (iteratee.call(context, obj[key], key, obj) === false) { + break; + } + } + } +} +/** + * Whether if inline node or not + * @param {Node} node Element + * @returns {boolean} + */ +// eslint-disable-next-line complexity + + +function isInlineNode(node) { + var tag = node.tagName; + return tag === 'S' || tag === 'B' || tag === 'I' || tag === 'EM' || tag === 'STRONG' || tag === 'A' || tag === 'IMG' || tag === 'CODE'; +} +/** + * Returns HTML string of an element using given subContent + * @param {Node} node Element + * @param {string} subContent string content of node + * @returns {string} + */ + + +function getRawHtmlString(node, subContent) { + var tempNode = node.cloneNode(false); + tempNode.innerHTML = subContent; + return tempNode.outerHTML; +} +/** + * Clone rules + * @param {object} destination object for apply rules + * @param {object} source source object for clone rules + */ + + +function cloneRules(destination, source) { + forEachOwnProperties(source, function (value, key) { + if (key !== 'converter') { + if (!destination[key]) { + destination[key] = {}; + } + + cloneRules(destination[key], value); + } else { + destination[key] = value; + } + }); +} +/** + * Renderer + * @param {object} [rules] rules to add + * @class + */ + + +var Renderer = /*#__PURE__*/function () { + function Renderer(rules) { + this.rules = {}; + /** + * Line feed replacement text + * @type string + */ + + this.lineFeedReplacement = "\u200B\u200B"; + + if (rules) { + this.addRules(rules); + } + } + /** + * Add rule + * @param {string} selectorString rule selector + * @param {function} converter converter function + */ + + + var _proto = Renderer.prototype; + + _proto.addRule = function addRule(selectorString, converter) { + var selectors = selectorString.split(', '); + var selector = selectors.pop(); + converter.fname = selectorString; + + while (selector) { + this._setConverterWithSelector(selector, converter); + + selector = selectors.pop(); + } + } + /** + * Add rules using object + * @param {object} rules key(rule selector), value(converter function) + */ + ; + + _proto.addRules = function addRules(rules) { + forEachOwnProperties(rules, function (converter, selectorString) { + this.addRule(selectorString, converter); + }, this); + } + /** + * Remove flanked space of dom node + * @param {string} content text content + * @param {HTMLElement} node current node + * @returns {string} result + */ + // eslint-disable-next-line complexity + ; + + _proto.getSpaceControlled = function getSpaceControlled(content, node) { + var lead = ''; + var trail = ''; + var text; + + if (node.previousSibling && (node.previousSibling.nodeType === TEXT_NODE || isInlineNode(node.previousSibling))) { + text = node.previousSibling.innerHTML || node.previousSibling.nodeValue; + + if (FIND_TRAIL_SPACE_RX.test(text) || FIND_LEAD_SPACE_RX.test(node.innerHTML || node.nodeValue)) { + lead = ' '; + } + } + + if (node.nextSibling && (node.nextSibling.nodeType === TEXT_NODE || isInlineNode(node.nextSibling))) { + text = node.nextSibling.innerHTML || node.nextSibling.nodeValue; + + if (FIND_LEAD_SPACE_RX.test(text) || FIND_TRAIL_SPACE_RX.test(node.innerHTML || node.nodeValue)) { + trail = ' '; + } + } + + return lead + content + trail; + } + /** + * Convert dom node to markdown using dom node and subContent + * @param {HTMLElement} node node to convert + * @param {string} subContent child nodes converted text + * @returns {string} converted text + */ + // eslint-disable-next-line complexity + ; + + _proto.convert = function convert(node, subContent) { + var result; + + var converter = this._getConverter(node); + + if (node && node.nodeType === Node.ELEMENT_NODE && node.hasAttribute('data-tomark-pass')) { + node.removeAttribute('data-tomark-pass'); + result = getRawHtmlString(node, subContent); + } else if (converter) { + result = converter.call(this, node, subContent); + } else if (node) { + result = this.getSpaceControlled(this._getInlineHtml(node, subContent), node); + } + + return result || ''; + }; + + _proto._getInlineHtml = function _getInlineHtml(node, subContent) { + var html = node.outerHTML; + var tagName = node.tagName; + var escapedSubContent = subContent.replace(/\$/g, '$$$$'); // escape $: replace all $ char to $$ before we throw this string to replace + + return html.replace(new RegExp("(<" + tagName + " ?.*?>).*()", 'i'), "$1" + escapedSubContent + "$2"); + } + /** + * Get converter function for node + * @private + * @param {HTMLElement} node node + * @returns {function} converter function + */ + ; + + _proto._getConverter = function _getConverter(node) { + var rulePointer = this.rules; + var converter; + + while (node && rulePointer) { + rulePointer = this._getNextRule(rulePointer, this._getRuleNameFromNode(node)); + node = this._getPrevNode(node); + + if (rulePointer && rulePointer.converter) { + converter = rulePointer.converter; + } + } + + return converter; + } + /** + * Get next rule object + * @private + * @param {object} ruleObj rule object + * @param {string} ruleName rule tag name to find + * @returns {object} rule Object + */ + ; + + _proto._getNextRule = function _getNextRule(ruleObj, ruleName) { + return ruleObj[ruleName]; + } + /** + * Get proper rule tag name from node + * @private + * @param {HTMLElement} node node + * @returns {string} rule tag name + */ + ; + + _proto._getRuleNameFromNode = function _getRuleNameFromNode(node) { + return node.tagName || 'TEXT_NODE'; + } + /** + * Get node's available parent node + * @private + * @param {HTMLElement} node node + * @returns {HTMLElement | undefined} result + */ + ; + + _proto._getPrevNode = function _getPrevNode(node) { + var parentNode = node.parentNode; + var previousNode; + + if (parentNode && !parentNode.__htmlRootByToMark) { + previousNode = parentNode; + } + + return previousNode; + } + /** + * Set converter for selector + * @private + * @param {string} selectors rule selector + * @param {function} converter converter function + */ + ; + + _proto._setConverterWithSelector = function _setConverterWithSelector(selectors, converter) { + var rulePointer = this.rules; + + this._eachSelector(selectors, function (ruleElem) { + if (!rulePointer[ruleElem]) { + rulePointer[ruleElem] = {}; + } + + rulePointer = rulePointer[ruleElem]; + }); + + rulePointer.converter = converter; + } + /** + * Iterate each selectors + * @private + * @param {string} selectors rule selectors + * @param {function} iteratee callback + */ + ; + + _proto._eachSelector = function _eachSelector(selectors, iteratee) { + var selectorArray = selectors.split(' '); + var selectorIndex = selectorArray.length - 1; + + while (selectorIndex >= 0) { + iteratee(selectorArray[selectorIndex]); + selectorIndex -= 1; + } + } + /** + * Trim text + * @param {string} text text be trimed + * @returns {string} trimed text + */ + ; + + _proto.trim = function trim(text) { + return text.replace(FIND_CHAR_TO_TRIM_RX, ''); + } + /** + * Returns whether text empty or not + * @param {string} text text be checked + * @returns {boolean} result + */ + ; + + _proto.isEmptyText = function isEmptyText(text) { + return text.replace(FIND_SPACE_RETURN_TAB_RX, '') === ''; + } + /** + * Collape space more than 2 + * @param {string} text text be collapsed + * @returns {string} result + */ + ; + + _proto.getSpaceCollapsedText = function getSpaceCollapsedText(text) { + return text.replace(FIND_SPACE_MORE_THAN_ONE_RX, ' '); + } + /** + * Apply backslash escape to text + * @param {string} text text be processed + * @returns {string} processed text + */ + ; + + _proto.escapeText = function escapeText(text) { + return text.replace(FIND_CHAR_TO_ESCAPE_RX, function (matched) { + return "\\" + matched; + }); + } + /** + * Escape given text for link + * @param {string} text - text be processed + * @returns {string} - processed text + */ + ; + + _proto.escapeTextForLink = function escapeTextForLink(text) { + var imageSyntaxRanges = []; + var result = FIND_MARKDOWN_IMAGE_SYNTAX_RX.exec(text); + + while (result) { + imageSyntaxRanges.push([result.index, result.index + result[0].length]); + result = FIND_MARKDOWN_IMAGE_SYNTAX_RX.exec(text); + } + + return text.replace(FIND_CHAR_TO_ESCAPE_IN_LINK_RX, function (matched, offset) { + var isDelimiter = imageSyntaxRanges.some(function (range) { + return offset > range[0] && offset < range[1]; + }); + return isDelimiter ? matched : "\\" + matched; + }); + } + /** + * Backslash escape to text for html + * Apply backslash escape to text + * @param {string} text text be processed + * @returns {string} processed text + */ + ; + + _proto.escapeTextHtml = function escapeTextHtml(text) { + return text.replace(new RegExp(Renderer.markdownTextToEscapeHtmlRx.source, 'g'), function (matched) { + return "\\" + matched; + }); + } + /** + * Backslash is using for escape ASCII punctuation character. + * https://spec.commonmark.org/0.29/#backslash-escapes + * If user input backslash as text, backslash is kept by inserting backslash. + * For example, if input text is "\$", this text is changed "\\$" + * @param {string} text text be processed + * @returns {string} processed text + */ + ; + + _proto.escapeTextBackSlash = function escapeTextBackSlash(text) { + return text.replace(new RegExp(Renderer.markdownTextToEscapeBackSlashRx.source, 'g'), function (matched) { + return "\\" + matched; + }); + } + /** + * Escapes in markdown paired characters + * @param {string} text Text to escape + * @returns {string} escaped text + */ + ; + + _proto.escapePairedCharacters = function escapePairedCharacters(text) { + return text.replace(new RegExp(Renderer.markdownTextToEscapePairedCharsRx.source, 'g'), function (matched) { + return "\\" + matched; + }); + }; + + _proto._isNeedEscape = function _isNeedEscape(text) { + var res = false; + var markdownTextToEscapeRx = Renderer.markdownTextToEscapeRx; + var type; + + for (type in markdownTextToEscapeRx) { + if (markdownTextToEscapeRx.hasOwnProperty(type) && markdownTextToEscapeRx[type].test(text)) { + res = true; + break; + } + } + + return res; + }; + + _proto._isNeedEscapeHtml = function _isNeedEscapeHtml(text) { + return Renderer.markdownTextToEscapeHtmlRx.test(text); + }; + + _proto._isNeedEscapeBackSlash = function _isNeedEscapeBackSlash(text) { + return Renderer.markdownTextToEscapeBackSlashRx.test(text); + }; + + _proto.mix = function mix(renderer) { + cloneRules(this.rules, renderer.rules); + } + /** + * Renderer factory + * Return new renderer + * @param {Renderer} srcRenderer renderer to extend + * @param {object} rules rule object, key(rule selector), value(converter function) + * @returns {Renderer} renderer + */ + ; + + Renderer.factory = function factory(srcRenderer, rules) { + var renderer = new Renderer(); + + if (!rules) { + rules = srcRenderer; + } else { + renderer.mix(srcRenderer); + } + + renderer.addRules(rules); + return renderer; + }; + + return Renderer; +}(); + +renderer_defineProperty(Renderer, "markdownTextToEscapeRx", { + codeblock: /(^ {4}[^\n]+\n*)+/, + hr: /^ *((\* *){3,}|(- *){3,} *|(_ *){3,}) */, + heading: /^(#{1,6}) +[\s\S]+/, + lheading: /^([^\n]+)\n *(=|-){2,} */, + blockquote: /^( *>[^\n]+.*)+/, + list: /^ *(\*+|-+|\d+\.) [\s\S]+/, + def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? */, + link: /!?\[.*\]\(.*\)/, + reflink: /!?\[.*\]\s*\[([^\]]*)\]/, + verticalBar: /\u007C/, + codeblockGfm: /^(`{3,})/, + codeblockTildes: /^(~{3,})/ +}); + +renderer_defineProperty(Renderer, "markdownTextToEscapeHtmlRx", /<([a-zA-Z_][a-zA-Z0-9\-._]*)(\s|[^\\/>])*\/?>|<(\/)([a-zA-Z_][a-zA-Z0-9\-._]*)\s*\/?>||<([a-zA-Z_][a-zA-Z0-9\-.:/]*)>/); + +renderer_defineProperty(Renderer, "markdownTextToEscapeBackSlashRx", /\\[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~\\]/); + +renderer_defineProperty(Renderer, "markdownTextToEscapePairedCharsRx", /[*_~`]/); + + +// CONCATENATED MODULE: ./src/renderer.basic.js +/** + * @fileoverview Implements basicRenderer + * @author NHN Ent. FE Development Lab + */ + +var FIND_LAST_RETURN_RX = /\n$/g; +var FIND_BR_AND_RETURN_RX = /[ \xA0]+\n\n/g; +var FIND_MULTIPLE_EMPTYLINE_BETWEEN_TEXT_RX = /([ \xA0]+\n){2,}/g; +var FIND_LINK_HREF = /href="(.*?)"/; +var START_OF_LINES_RX = /^/gm; +/** + * Basic Markdown Renderer + * @exports basicRenderer + * @augments Renderer + */ + +/* harmony default export */ var renderer_basic = (Renderer.factory({ + // inlines + TEXT_NODE: function TEXT_NODE(node) { + var managedText = this.trim(this.getSpaceCollapsedText(node.nodeValue)); + + if (this._isNeedEscapeBackSlash(managedText)) { + managedText = this.escapeTextBackSlash(managedText); + } + + managedText = this.escapePairedCharacters(managedText); + + if (this._isNeedEscapeHtml(managedText)) { + managedText = this.escapeTextHtml(managedText); + } + + if (this._isNeedEscape(managedText)) { + managedText = this.escapeText(managedText); + } + + return this.getSpaceControlled(managedText, node); + }, + 'CODE TEXT_NODE': function CODETEXT_NODE(node) { + return node.nodeValue; + }, + 'EM, I': function EMI(node, subContent) { + var res = ''; + + if (!this.isEmptyText(subContent)) { + res = "*" + subContent + "*"; + } + + return res; + }, + 'STRONG, B': function STRONGB(node, subContent) { + var res = ''; + + if (!this.isEmptyText(subContent)) { + res = "**" + subContent + "**"; + } + + return res; + }, + A: function A(node, subContent) { + var res = subContent; + var title = ''; + var url; // "href" attribute is difficult to predict depending on the situation + // so use as it is applied to html + + var foundedHref = FIND_LINK_HREF.exec(node.outerHTML); + + if (foundedHref) { + url = foundedHref[1].replace(/&/g, '&'); + } + + if (node.title) { + title = " \"" + node.title + "\""; + } + + if (!this.isEmptyText(subContent) && url) { + res = "[" + this.escapeTextForLink(subContent) + "](" + url + title + ")"; + } + + return res; + }, + IMG: function IMG(node) { + var src = node.getAttribute('src'); + var alt = node.alt; + + if (src) { + return "![" + this.escapeTextForLink(alt) + "](" + src + ")"; + } + + return ''; + }, + BR: function BR() { + return ' \n'; + }, + CODE: function CODE(node, subContent) { + var backticks, numBackticks; + var res = ''; + + if (!this.isEmptyText(subContent)) { + numBackticks = parseInt(node.getAttribute('data-backticks'), 10); + backticks = isNaN(numBackticks) ? '`' : Array(numBackticks + 1).join('`'); + res = backticks + subContent + backticks; + } + + return res; + }, + // Paragraphs + P: function P(node, subContent) { + var res = ''; // convert multiple brs to one br + + subContent = subContent.replace(FIND_MULTIPLE_EMPTYLINE_BETWEEN_TEXT_RX, ' \n'); + + if (!this.isEmptyText(subContent)) { + res = "\n\n" + subContent + "\n\n"; + } + + return res; + }, + 'BLOCKQUOTE P': function BLOCKQUOTEP(node, subContent) { + return subContent; + }, + 'LI P': function LIP(node, subContent) { + var res = ''; + + if (!this.isEmptyText(subContent)) { + res = subContent; + } + + return res; + }, + // Headings + 'H1, H2, H3, H4, H5, H6': function H1H2H3H4H5H6(node, subContent) { + var res = ''; + var headingNumber = parseInt(node.tagName.charAt(1), 10); + + while (headingNumber) { + res += '#'; + headingNumber -= 1; + } + + res += ' '; + res += subContent; + return "\n\n" + res + "\n\n"; + }, + 'LI H1, LI H2, LI H3, LI H4, LI H5, LI H6': function LIH1LIH2LIH3LIH4LIH5LIH6(node, subContent) { + var headingNumber = parseInt(node.tagName.charAt(1), 10); + return Array(headingNumber + 1).join('#') + " " + subContent; + }, + // List + 'UL, OL': function ULOL(node, subContent) { + return "\n\n" + subContent + "\n\n"; + }, + 'LI OL, LI UL': function LIOLLIUL(node, subContent) { + var processedSubContent; // remove last br of li + + processedSubContent = subContent.replace(FIND_BR_AND_RETURN_RX, '\n'); // parent LI converter add \n too, so we remove last return + + processedSubContent = processedSubContent.replace(FIND_LAST_RETURN_RX, ''); + var res = processedSubContent.replace(START_OF_LINES_RX, ' '); + return "\n" + res; + }, + 'UL LI': function ULLI(node, subContent) { + var res = ''; // convert multiple brs to one br + + subContent = subContent.replace(FIND_MULTIPLE_EMPTYLINE_BETWEEN_TEXT_RX, ' \n'); + + if (node.firstChild && node.firstChild.tagName === 'P') { + res += '\n'; + } + + res += "* " + subContent + "\n"; + return res; + }, + // eslint-disable-next-line complexity + 'OL LI': function OLLI(node, subContent) { + var res = ''; + var liCounter = parseInt(node.parentNode.getAttribute('start') || 1, 10); + + while (node.previousSibling) { + node = node.previousSibling; + + if (node.nodeType === 1 && node.tagName === 'LI') { + liCounter += 1; + } + } // convert multiple brs to one br + + + subContent = subContent.replace(FIND_MULTIPLE_EMPTYLINE_BETWEEN_TEXT_RX, ' \n'); + + if (node.firstChild && node.firstChild.tagName === 'P') { + res += '\n'; + } + + res += liCounter + ". " + subContent + "\n"; + return res; + }, + // HR + HR: function HR() { + return '\n\n- - -\n\n'; + }, + // Blockquote + BLOCKQUOTE: function BLOCKQUOTE(node, subContent) { + // convert multiple brs to one emptyline + subContent = subContent.replace(FIND_MULTIPLE_EMPTYLINE_BETWEEN_TEXT_RX, '\n\n'); + var trimmedText = this.trim(subContent); + var res = trimmedText.replace(START_OF_LINES_RX, '> '); + return "\n\n" + res + "\n\n"; + }, + // Code Block + 'PRE CODE': function PRECODE(node, subContent) { + var lastNremoved = subContent.replace(FIND_LAST_RETURN_RX, ''); + var res = lastNremoved.replace(START_OF_LINES_RX, ' '); + return "\n\n" + res + "\n\n"; + } +})); +// CONCATENATED MODULE: ./src/renderer.gfm.js +/** + * @fileoverview Implements Github flavored markdown renderer + * @author NHN Ent. FE Development Lab + */ + + +/** + * gfmRenderer + * github flavored Markdown Renderer + * + * we didnt render gfm br here because we need distingush returns that made by block with br + * so we render gfm br later in toMark.js finalize function + * @exports gfmRenderer + * @augments Renderer + */ + +/* harmony default export */ var renderer_gfm = (Renderer.factory(renderer_basic, { + 'DEL, S': function DELS(node, subContent) { + return "~~" + subContent + "~~"; + }, + 'PRE CODE': function PRECODE(node, subContent) { + var language = ''; + var numberOfBackticks = node.getAttribute('data-backticks'); + + if (node.getAttribute('data-language')) { + language = " " + node.getAttribute('data-language'); + } + + numberOfBackticks = parseInt(numberOfBackticks, 10); + var backticks = isNaN(numberOfBackticks) ? '```' : Array(numberOfBackticks + 1).join('`'); + subContent = subContent.replace(/(\r\n)|(\r)|(\n)/g, this.lineFeedReplacement); + return "\n\n" + backticks + language + "\n" + subContent + "\n" + backticks + "\n\n"; + }, + PRE: function PRE(node, subContent) { + return subContent; + }, + 'UL LI': function ULLI(node, subContent) { + return renderer_basic.convert(node, makeTaskIfNeed(node, subContent)); + }, + 'OL LI': function OLLI(node, subContent) { + return renderer_basic.convert(node, makeTaskIfNeed(node, subContent)); + }, + // Table + TABLE: function TABLE(node, subContent) { + return "\n\n" + subContent + "\n\n"; + }, + 'TBODY, TFOOT': function TBODYTFOOT(node, subContent) { + return subContent; + }, + 'TR TD, TR TH': function TRTDTRTH(node, subContent) { + subContent = subContent.replace(/(\r\n)|(\r)|(\n)/g, ''); + return " " + subContent + " |"; + }, + 'TD BR, TH BR': function TDBRTHBR() { + return '
'; + }, + TR: function TR(node, subContent) { + return "|" + subContent + "\n"; + }, + THEAD: function THEAD(node, subContent) { + var result = ''; + var ths = findChildTag(findChildTag(node, 'TR')[0], 'TH'); + + for (var i = 0, thsLength = ths.length; i < thsLength; i += 1) { + result += " " + makeTableHeadAlignText(ths[i]) + " |"; + } + + return subContent ? subContent + "|" + result + "\n" : ''; + } +})); +/** + * Make task Markdown string if need + * @param {HTMLElement} node Passed HTML Element + * @param {string} subContent node's content + * @returns {string} + */ + +function makeTaskIfNeed(node, subContent) { + var condition; + + if (node.className.indexOf('task-list-item') !== -1) { + condition = node.className.indexOf('checked') !== -1 ? 'x' : ' '; + subContent = "[" + condition + "] " + subContent; + } + + return subContent; +} +/** + * Make table head align text + * @param {HTMLElement} th Table head cell element + * @returns {string} + */ + + +function makeTableHeadAlignText(th) { + var leftAlignValue, rightAlignValue, textLength; + var align = th.align; + textLength = th.textContent ? th.textContent.length : th.innerText.length; + leftAlignValue = ''; + rightAlignValue = ''; + + if (align) { + if (align === 'left') { + leftAlignValue = ':'; + textLength -= 1; + } else if (align === 'right') { + rightAlignValue = ':'; + textLength -= 1; + } else if (align === 'center') { + rightAlignValue = ':'; + leftAlignValue = ':'; + textLength -= 2; + } + } + + return leftAlignValue + repeatString('-', textLength) + rightAlignValue; +} +/** + * Find child element of given tag name + * @param {HTMLElement} node starting element + * @param {string} tagName Tag name for search + * @returns {Array.} + */ + + +function findChildTag(node, tagName) { + var childNodes = node.childNodes; + var result = []; + + for (var i = 0, childLength = childNodes.length; i < childLength; i += 1) { + if (childNodes[i].tagName && childNodes[i].tagName === tagName) { + result.push(childNodes[i]); + } + } + + return result; +} +/** + * Repeat given string + * @param {string} pattern String for repeat + * @param {number} count Amount of repeat + * @returns {string} + */ + + +function repeatString(pattern, count) { + var result = pattern; + count = Math.max(count, 3); + + while (count > 1) { + result += pattern; + count -= 1; + } + + return result; +} +// CONCATENATED MODULE: ./src/toMark.js +/** + * @fileoverview Implements toMark + * @author NHN Ent. FE Development Lab + */ + + + + +var FIND_UNUSED_BRS_RX = /[ \xA0]+(\n\n)/g; +var FIND_FIRST_LAST_WITH_SPACE_RETURNS_RX = /^[\n]+|[\s\n]+$/g; +var FIND_MULTIPLE_BRS_RX = /([ \xA0]+\n){2,}/g; +var FIND_RETURNS_RX = /([ \xA0]){2,}\n/g; +var FIND_RETURNS_AND_SPACE_RX = /[ \xA0\n]+/g; +/** + * @exports toMark + * @param {string} htmlStr html string to convert + * @param {object} options option + * @param {boolean} options.gfm if this property is false turn off it cant parse gfm + * @param {Renderer} options.renderer pass renderer to use + * @returns {string} converted markdown text + * @example + * toMark('

hello world

'); // "# hello world" + * toMark('strike'); // "~~strike~~" + * toMark('strike', {gfm: false}); // "strike" + */ + +function toMark(htmlStr, options) { + var isGfm = true; + var renderer; + + if (!htmlStr) { + return ''; + } + + renderer = renderer_gfm; + + if (options) { + isGfm = options.gfm; + + if (isGfm === false) { + renderer = renderer_basic; + } + + renderer = options.renderer || renderer; + } + + var runner = new DomRunner(toDom(htmlStr)); + return finalize(parse(runner, renderer), isGfm, renderer.lineFeedReplacement); +} +/** + * Parse dom to markdown + * @param {DomRunner} runner runner + * @param {Renderer} renderer renderer + * @returns {string} markdown text + */ + +function parse(runner, renderer) { + var markdownContent = ''; + + while (runner.next()) { + markdownContent += tracker(runner, renderer); + } + + return markdownContent; +} +/** + * Remove first and last return character + * @param {string} text text to finalize + * @param {boolean} isGfm isGfm flag + * @param {string} lineFeedReplacement Line feed replacement text + * @returns {string} result + */ + + +function finalize(text, isGfm, lineFeedReplacement) { + // collapse return and
+ text = text.replace(FIND_UNUSED_BRS_RX, '\n'); // collapse multiple br + + text = text.replace(FIND_MULTIPLE_BRS_RX, '\n\n'); + text = text.replace(FIND_RETURNS_AND_SPACE_RX, function (matched) { + var returnCount = (matched.match(/\n/g) || []).length; + + if (returnCount >= 3) { + return '\n\n'; + } + + if (matched >= 1) { + return '\n'; + } + + return matched; + }); // remove first and last \n + + text = text.replace(FIND_FIRST_LAST_WITH_SPACE_RETURNS_RX, ''); + text = text.replace(new RegExp(lineFeedReplacement, 'g'), '\n'); // in gfm replace ' \n' make by
to '\n' + + if (isGfm) { + text = text.replace(FIND_RETURNS_RX, '\n'); + } + + return text; +} +/** + * Iterate childNodes and process conversion using recursive call + * @param {DomRunner} runner dom runner + * @param {Renderer} renderer renderer to use + * @returns {string} processed text + */ + + +function tracker(runner, renderer) { + var subContent = ''; + var node = runner.getNode(); + + for (var i = 0, t = node.childNodes.length; i < t; i += 1) { + runner.next(); + subContent += tracker(runner, renderer); + } + + return renderer.convert(node, subContent); +} +// CONCATENATED MODULE: ./src/index.js +/** + * @fileoverview Implements entry point + * @author NHN Ent. FE Development Lab + */ + + + + +toMark.Renderer = Renderer; +toMark.basicRenderer = renderer_basic; +toMark.gfmRenderer = renderer_gfm; +/* harmony default export */ var src = __webpack_exports__["default"] = (toMark); + +/***/ }) +/******/ ])["default"]; +}); + +/***/ }), +/* 33 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Get HTML element's design classes. + * @author NHN FE Development Lab + */ + + + +var isUndefined = __webpack_require__(8); + +/** + * Get HTML element's design classes. + * @param {(HTMLElement|SVGElement)} element target element + * @returns {string} element css class name + * @memberof module:domUtil + */ +function getClass(element) { + if (!element || !element.className) { + return ''; + } + + if (isUndefined(element.className.baseVal)) { + return element.className; + } + + return element.className.baseVal; +} + +module.exports = getClass; + + +/***/ }), +/* 34 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is a number or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is a number or not. + * If the given variable is a number, return true. + * @param {*} obj - Target for checking + * @returns {boolean} Is number? + * @memberof module:type + */ +function isNumber(obj) { + return typeof obj === 'number' || obj instanceof Number; +} + +module.exports = isNumber; + + +/***/ }), +/* 35 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export CLASS_HIGHLIGHT */ +/* harmony import */ var tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(19); +/* harmony import */ var tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); +/* harmony import */ var tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5); +/* harmony import */ var tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6); +/* harmony import */ var tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(22); +/* harmony import */ var _toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_4__); +/* harmony import */ var _preview__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(38); +/* harmony import */ var _utils_dom__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(0); +/* harmony import */ var _htmlRenderConvertors__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(29); +/* harmony import */ var _scroll_helper__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(18); +/* harmony import */ var _scroll_cache_offsetInfo__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(24); +/* harmony import */ var _utils_markdown__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(2); +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements markdown preview + * @author NHN FE Development Lab + */ + + + + + + + + + + + +var CLASS_HIGHLIGHT = 'te-preview-highlight'; + +function findTableCell(tableRow, _ref) { + var ch = _ref.ch; + var cell = tableRow.firstChild; + + while (cell && cell.next) { + if (Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_10__[/* getMdStartCh */ "e"])(cell.next) > ch + 1) { + break; + } + + cell = cell.next; + } + + return cell; +} +/** + * Class Markdown Preview + * @param {HTMLElement} el - base element + * @param {EventManager} eventManager - event manager + * @param {Convertor} convertor - convertor + * @param {object} options + * @param {boolean} options.isViewer - true for view-only mode + * @param {boolean} options.highlight - true for using live-highlight feature + * @param {object} opitons.linkAttribute - attributes for link element + * @param {object} opitons.customHTMLRenderer - map of custom HTML render functions + + * @ignore + */ + + +var MarkdownPreview = /*#__PURE__*/function (_Preview) { + _inheritsLoose(MarkdownPreview, _Preview); + + function MarkdownPreview(el, eventManager, convertor, options) { + var _this; + + _this = _Preview.call(this, el, eventManager, convertor, options.isViewer) || this; + + _this.lazyRunner.registerLazyRunFunction('invokeCodeBlock', _this.invokeCodeBlockPlugins, _this.delayCodeBlockTime, _assertThisInitialized(_this)); + + var linkAttribute = options.linkAttribute, + customHTMLRenderer = options.customHTMLRenderer, + _options$highlight = options.highlight, + highlight = _options$highlight === void 0 ? false : _options$highlight; + _this.renderHTML = Object(_toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_4__["createRenderHTML"])({ + gfm: true, + nodeId: true, + convertors: Object(_htmlRenderConvertors__WEBPACK_IMPORTED_MODULE_7__[/* getHTMLRenderConvertors */ "a"])(linkAttribute, customHTMLRenderer) + }); + _this.cursorNodeId = null; + + _this._initEvent(highlight); + + return _this; + } + /** + * Initialize event + * @private + */ + + + var _proto = MarkdownPreview.prototype; + + _proto._initEvent = function _initEvent(highlight) { + var _this2 = this; + + this.eventManager.listen('contentChangedFromMarkdown', this.update.bind(this)); // need to implement a listener function for 'previewNeedsRefresh' event + // to support third-party plugins which requires re-executing script for every re-render + + if (highlight) { + this.eventManager.listen('cursorActivity', function (_ref2) { + var markdownNode = _ref2.markdownNode, + cursor = _ref2.cursor; + + _this2._updateCursorNode(markdownNode, cursor); + }); + this.eventManager.listen('blur', function () { + _this2._removeHighlight(); + }); + } + + tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_0___default()(this.el, 'scroll', function (event) { + _this2.eventManager.emit('scroll', { + source: 'preview', + data: Object(_scroll_helper__WEBPACK_IMPORTED_MODULE_8__[/* findAdjacentElementToScrollTop */ "a"])(event.target.scrollTop, _this2._previewContent) + }); + }); + }; + + _proto._removeHighlight = function _removeHighlight() { + if (this.cursorNodeId) { + var currentEl = this._getElementByNodeId(this.cursorNodeId); + + if (currentEl) { + tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_3___default()(currentEl, CLASS_HIGHLIGHT); + } + } + }; + + _proto._updateCursorNode = function _updateCursorNode(cursorNode, cursorPos) { + if (cursorNode) { + cursorNode = Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_10__[/* findClosestNode */ "b"])(cursorNode, function (mdNode) { + return !Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_10__[/* isInlineNode */ "h"])(mdNode); + }); + + if (cursorNode.type === 'tableRow') { + cursorNode = findTableCell(cursorNode, cursorPos); + } else if (cursorNode.type === 'tableBody') { + // empty line next to table + cursorNode = null; + } + } + + var cursorNodeId = cursorNode ? cursorNode.id : null; + + if (this.cursorNodeId === cursorNodeId) { + return; + } + + var inFrontMatter = cursorNode && cursorNode.customType === 'frontMatter'; + + var oldEL = this._getElementByNodeId(this.cursorNodeId); + + var newEL = this._getElementByNodeId(cursorNodeId); + + if (oldEL) { + tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_3___default()(oldEL, CLASS_HIGHLIGHT); + } + + if (newEL && !inFrontMatter) { + tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_2___default()(newEL, CLASS_HIGHLIGHT); + } + + this.cursorNodeId = cursorNodeId; + }; + + _proto._getElementByNodeId = function _getElementByNodeId(nodeId) { + if (!nodeId) { + return null; + } + + return this._previewContent.querySelector("[data-nodeid=\"" + nodeId + "\"]"); + }; + + _proto.update = function update(changed) { + var _this3 = this; + + changed.forEach(function (editResult) { + return _this3.replaceRangeNodes(editResult); + }); + this.eventManager.emit('previewRenderAfter', this); + }; + + _proto.replaceRangeNodes = function replaceRangeNodes(editResult) { + var _this4 = this; + + var nodes = editResult.nodes, + removedNodeRange = editResult.removedNodeRange; + var contentEl = this._previewContent; + var newHtml = this.eventManager.emitReduce('convertorAfterMarkdownToHtmlConverted', nodes.map(function (node) { + return _this4.renderHTML(node); + }).join('')); + + if (!removedNodeRange) { + contentEl.insertAdjacentHTML('afterbegin', newHtml); + } else { + var _removedNodeRange$id = removedNodeRange.id, + startNodeId = _removedNodeRange$id[0], + endNodeId = _removedNodeRange$id[1]; + + var startEl = this._getElementByNodeId(startNodeId); + + var endEl = this._getElementByNodeId(endNodeId); + + if (startEl) { + startEl.insertAdjacentHTML('beforebegin', newHtml); + var el = startEl; + + while (el !== endEl) { + var nextEl = el.nextElementSibling; + el.parentNode.removeChild(el); + Object(_scroll_cache_offsetInfo__WEBPACK_IMPORTED_MODULE_9__[/* removeOffsetInfoByNode */ "c"])(el); + el = nextEl; + } + + if (el.parentNode) { + _utils_dom__WEBPACK_IMPORTED_MODULE_6__[/* default */ "a"].remove(el); + Object(_scroll_cache_offsetInfo__WEBPACK_IMPORTED_MODULE_9__[/* removeOffsetInfoByNode */ "c"])(el); + } + } + } + + var codeBlockEls = this.getCodeBlockElements(nodes.map(function (node) { + return node.id; + })); + + if (codeBlockEls.length) { + this.lazyRunner.run('invokeCodeBlock', codeBlockEls); + } + } + /** + * render + * @param {string} html - html string to render + * @override + */ + ; + + _proto.render = function render(html) { + _Preview.prototype.render.call(this, html); + + this.eventManager.emit('previewRenderAfter', this); + }; + + _proto.remove = function remove() { + tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_1___default()(this.el, 'scroll'); + this.el = null; + }; + + return MarkdownPreview; +}(_preview__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"]); + +/* harmony default export */ __webpack_exports__["a"] = (MarkdownPreview); + +/***/ }), +/* 36 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var tui_code_snippet_type_isFalsy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(44); +/* harmony import */ var tui_code_snippet_type_isFalsy__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isFalsy__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var tui_code_snippet_enum_enum__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(45); +/* harmony import */ var tui_code_snippet_enum_enum__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_enum_enum__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _utils_map__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(23); +/** + * @fileoverview Implements EventManager + * @author NHN FE Development Lab + */ + + + + + +var eventList = ['previewBeforeHook', 'previewRenderAfter', 'previewNeedsRefresh', 'addImageBlobHook', 'setMarkdownAfter', 'contentChangedFromWysiwyg', 'changeFromWysiwyg', 'contentChangedFromMarkdown', 'changeFromMarkdown', 'change', 'changeModeToWysiwyg', 'changeModeToMarkdown', 'changeModeBefore', 'changeMode', 'changePreviewStyle', 'changePreviewTabPreview', 'changePreviewTabWrite', 'openPopupAddLink', 'openPopupAddImage', 'openPopupAddTable', 'openPopupTableUtils', 'openHeadingSelect', 'openPopupCodeBlockLanguages', 'openPopupCodeBlockEditor', 'openDropdownToolbar', 'closePopupCodeBlockLanguages', 'closePopupCodeBlockEditor', 'closeAllPopup', 'command', 'addCommandBefore', 'htmlUpdate', 'markdownUpdate', 'renderedHtmlUpdated', 'removeEditor', 'convertorAfterMarkdownToHtmlConverted', 'convertorBeforeHtmlToMarkdownConverted', 'convertorAfterHtmlToMarkdownConverted', 'stateChange', 'wysiwygSetValueAfter', 'wysiwygSetValueBefore', 'wysiwygGetValueBefore', 'wysiwygProcessHTMLText', 'wysiwygRangeChangeAfter', 'wysiwygKeyEvent', 'scroll', 'click', 'mousedown', 'mouseover', 'mouseout', 'mouseup', 'contextmenu', 'keydown', 'keyup', 'keyMap', 'load', 'focus', 'blur', 'paste', 'pasteBefore', 'willPaste', 'copy', 'copyBefore', 'copyAfter', 'cut', 'cutAfter', 'drop', 'show', 'hide', 'changeLanguage', 'cursorActivity', 'requireScrollSync', 'requireScrollIntoView', 'setCodeBlockLanguages']; +/** + * Class EventManager + * @ignore + */ + +var EventManager = /*#__PURE__*/function () { + function EventManager() { + this.events = new _utils_map__WEBPACK_IMPORTED_MODULE_4__[/* default */ "a"](); + this.TYPE = new tui_code_snippet_enum_enum__WEBPACK_IMPORTED_MODULE_3___default.a(eventList); + } + /** + * Listen event and bind event handler + * @param {string} typeStr Event type string + * @param {function} handler Event handler + */ + + + var _proto = EventManager.prototype; + + _proto.listen = function listen(typeStr, handler) { + var typeInfo = this._getTypeInfo(typeStr); + + var eventHandlers = this.events.get(typeInfo.type) || []; + + if (!this._hasEventType(typeInfo.type)) { + throw new Error("There is no event type " + typeInfo.type); + } + + if (typeInfo.namespace) { + handler.namespace = typeInfo.namespace; + } + + eventHandlers.push(handler); + this.events.set(typeInfo.type, eventHandlers); + } + /** + * Emit event + * @param {string} eventName Event name to emit + * @returns {Array} + */ + ; + + _proto.emit = function emit() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var typeStr = args.shift(); + + var typeInfo = this._getTypeInfo(typeStr); + + var eventHandlers = this.events.get(typeInfo.type); + var results; + + if (eventHandlers) { + tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default()(eventHandlers, function (handler) { + var result = handler.apply(void 0, args); + + if (!tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(result)) { + results = results || []; + results.push(result); + } + }); + } + + return results; + } + /** + * Emit given event and return result + * @param {string} eventName Event name to emit + * @param {string} sourceText Source text to change + * @returns {string} + */ + ; + + _proto.emitReduce = function emitReduce() { + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + var type = args.shift(); + var eventHandlers = this.events.get(type); + + if (eventHandlers) { + tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default()(eventHandlers, function (handler) { + var result = handler.apply(void 0, args); + + if (!tui_code_snippet_type_isFalsy__WEBPACK_IMPORTED_MODULE_2___default()(result)) { + args[0] = result; + } + }); + } + + return args[0]; + } + /** + * Get event type and namespace + * @param {string} typeStr Event type name + * @returns {{type: string, namespace: string}} + * @private + */ + ; + + _proto._getTypeInfo = function _getTypeInfo(typeStr) { + var splited = typeStr.split('.'); + return { + type: splited[0], + namespace: splited[1] + }; + } + /** + * Check whether event type exists or not + * @param {string} type Event type name + * @returns {boolean} + * @private + */ + ; + + _proto._hasEventType = function _hasEventType(type) { + return !tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(this.TYPE[this._getTypeInfo(type).type]); + } + /** + * Add event type when given event not exists + * @param {string} type Event type name + */ + ; + + _proto.addEventType = function addEventType(type) { + if (this._hasEventType(type)) { + throw new Error("There is already have event type " + type); + } + + this.TYPE.set(type); + } + /** + * Remove event handler from given event type + * @param {string} typeStr Event type name + * @param {function} [handler] - registered event handler + */ + ; + + _proto.removeEventHandler = function removeEventHandler(typeStr, handler) { + var _this = this; + + var _this$_getTypeInfo = this._getTypeInfo(typeStr), + type = _this$_getTypeInfo.type, + namespace = _this$_getTypeInfo.namespace; + + if (type && handler) { + this._removeEventHandlerWithHandler(type, handler); + } else if (type && !namespace) { + // dont use dot notation cuz eslint + this.events.delete(type); + } else if (!type && namespace) { + this.events.forEach(function (eventHandlers, eventType) { + _this._removeEventHandlerWithTypeInfo(eventType, namespace); + }); + } else if (type && namespace) { + this._removeEventHandlerWithTypeInfo(type, namespace); + } + } + /** + * Remove event handler with event handler + * @param {string} type - event type name + * @param {function} handler - event handler + * @private + */ + ; + + _proto._removeEventHandlerWithHandler = function _removeEventHandlerWithHandler(type, handler) { + var eventHandlers = this.events.get(type) || []; + var handlerIndex = eventHandlers.indexOf(handler); + + if (handlerIndex >= 0) { + eventHandlers.splice(handlerIndex, 1); + } + } + /** + * Remove event handler with event type information + * @param {string} type Event type name + * @param {string} namespace Event namespace + * @private + */ + ; + + _proto._removeEventHandlerWithTypeInfo = function _removeEventHandlerWithTypeInfo(type, namespace) { + var handlersToSurvive = []; + var eventHandlers = this.events.get(type); + + if (!eventHandlers) { + return; + } + + eventHandlers.map(function (handler) { + if (handler.namespace !== namespace) { + handlersToSurvive.push(handler); + } + + return null; + }); + this.events.set(type, handlersToSurvive); + }; + + return EventManager; +}(); + +/* harmony default export */ __webpack_exports__["a"] = (EventManager); + +/***/ }), +/* 37 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var _toast_ui_to_mark__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(32); +/* harmony import */ var _toast_ui_to_mark__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_toast_ui_to_mark__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(22); +/* harmony import */ var _toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var _htmlRenderConvertors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); +/* harmony import */ var _utils_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(0); +/** + * @fileoverview Convertor have responsible to convert markdown and html + * @author NHN FE Development Lab + */ + + + + // This regular expression refere markdownIt. +// https://github.com/markdown-it/markdown-it/blob/master/lib/common/html_re.js + +var attrName = '[a-zA-Z_:][a-zA-Z0-9:._-]*'; +var unquoted = '[^"\'=<>`\\x00-\\x20]+'; +var singleQuoted = "'[^']*'"; +var doubleQuoted = '"[^"]*"'; +var attrValue = "(?:" + unquoted + "|" + singleQuoted + "|" + doubleQuoted + ")"; +var attribute = "(?:\\s+" + attrName + "(?:\\s*=\\s*" + attrValue + ")?)*\\s*"; +var openingTag = "(\\\\<|<)([A-Za-z][A-Za-z0-9\\-]*" + attribute + ")(\\/?>)"; +var HTML_TAG_RX = new RegExp(openingTag, 'g'); +var FRONT_MATTER_RX = /^\s?\\-\\-\\-([\s\S]+?)\\-\\-\\-/; +/** + * Class Convertor + * @param {EventManager} em - EventManager instance + * @ignore + */ + +var Convertor = /*#__PURE__*/function () { + function Convertor(em, options) { + if (options === void 0) { + options = {}; + } + + var _options = options, + linkAttribute = _options.linkAttribute, + customHTMLRenderer = _options.customHTMLRenderer, + extendedAutolinks = _options.extendedAutolinks, + referenceDefinition = _options.referenceDefinition, + customParser = _options.customParser, + frontMatter = _options.frontMatter, + customProp = _options.customProp; + this.options = options; + this.mdReader = new _toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_1__["Parser"]({ + extendedAutolinks: extendedAutolinks, + disallowedHtmlBlockTags: ['br'], + referenceDefinition: referenceDefinition, + disallowDeepHeading: true, + customParser: customParser, + frontMatter: frontMatter + }); + this.renderHTML = Object(_toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_1__["createRenderHTML"])({ + gfm: true, + convertors: Object(_htmlRenderConvertors__WEBPACK_IMPORTED_MODULE_2__[/* getHTMLRenderConvertors */ "a"])(linkAttribute, customHTMLRenderer), + customProp: customProp + }); + this.eventManager = em; + } + /** + * _markdownToHtmlWithCodeHighlight + * Convert markdown to html with Codehighlight + * @param {string} markdown markdown text + * @returns {string} html text + * @private + */ + + + var _proto = Convertor.prototype; + + _proto._markdownToHtmlWithCodeHighlight = function _markdownToHtmlWithCodeHighlight(markdown) { + return this.renderHTML(this.mdReader.parse(markdown)); + } + /** + * _markdownToHtml + * Convert markdown to html + * @param {string} markdown markdown text + * @param {object} env environment sandbox for markdownit + * @returns {string} html text + * @private + */ + ; + + _proto._markdownToHtml = function _markdownToHtml(markdown) { + markdown = markdown.replace(HTML_TAG_RX, function (match, $1, $2, $3) { + return match[0] !== '\\' ? "" + $1 + $2 + " data-tomark-pass " + $3 : match; + }); + return this.renderHTML(this.mdReader.parse(markdown)); + } + /** + * Remove BR's data-tomark-pass attribute text when br in code element + * @param {string} renderedHTML Rendered HTML string from markdown editor + * @returns {string} + * @private + */ + ; + + _proto._removeBrToMarkPassAttributeInCode = function _removeBrToMarkPassAttributeInCode(renderedHTML) { + var wrapper = _utils_dom__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"].createElementWith("
" + renderedHTML + "
"); + _utils_dom__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"].findAll(wrapper, 'code, pre').forEach(function (codeOrPre) { + var codeEelement = codeOrPre; + codeEelement.innerHTML = codeEelement.innerHTML.replace(/\sdata-tomark-pass\s(\/?)>/g, '$1>'); + }); + renderedHTML = wrapper.innerHTML; + return renderedHTML; + } + /** + * toHTMLWithCodeHighlight + * Convert markdown to html with Codehighlight + * emit convertorAfterMarkdownToHtmlConverted + * @param {string} markdown markdown text + * @returns {string} html text + */ + ; + + _proto.toHTMLWithCodeHighlight = function toHTMLWithCodeHighlight(markdown) { + var html = this._markdownToHtmlWithCodeHighlight(markdown); + + html = this.eventManager.emitReduce('convertorAfterMarkdownToHtmlConverted', html); + return html; + } + /** + * toHTML + * Convert markdown to html + * emit convertorAfterMarkdownToHtmlConverted + * @param {string} markdown markdown text + * @returns {string} html text + */ + ; + + _proto.toHTML = function toHTML(markdown) { + var html = this._markdownToHtml(markdown); + + html = this.eventManager.emitReduce('convertorAfterMarkdownToHtmlConverted', html); + html = this._removeBrToMarkPassAttributeInCode(html); + return html; + }; + + _proto.initHtmlSanitizer = function initHtmlSanitizer(sanitizer) { + this.eventManager.listen('convertorAfterMarkdownToHtmlConverted', function (html) { + return sanitizer(html, true); + }); + } + /** + * toMarkdown + * Convert html to markdown + * emit convertorAfterHtmlToMarkdownConverted + * @param {string} html html text + * @param {object | null} toMarkOptions - toMark library options + * @returns {string} markdown text + */ + ; + + _proto.toMarkdown = function toMarkdown(html, toMarkOptions) { + var result = []; + html = this.eventManager.emitReduce('convertorBeforeHtmlToMarkdownConverted', html); + html = this._appendAttributeForLinkIfNeed(html); + html = this._appendAttributeForBrIfNeed(html); + var markdown = _toast_ui_to_mark__WEBPACK_IMPORTED_MODULE_0___default()(html, toMarkOptions); + + if (this.options.frontMatter) { + markdown = markdown.replace(FRONT_MATTER_RX, '---$1---'); + } + + markdown = this.eventManager.emitReduce('convertorAfterHtmlToMarkdownConverted', markdown); + markdown = this._removeNewlinesBeforeAfterAndBlockElement(markdown); + markdown.split('\n').forEach(function (line, index) { + var FIND_TABLE_RX = /^(
)+\||\|[^|]*\|/gi; + var FIND_CODE_RX = /`[^`]*
[^`]*`/gi; + var FIND_BRS_BEFORE_TABLE = /^(
)+\|/gi; + + if (FIND_TABLE_RX.test(line)) { + line = line.replace(FIND_BRS_BEFORE_TABLE, function (match) { + return match.replace(/
/gi, '
\n'); + }); + } else if (!FIND_CODE_RX.test(line)) { + line = line.replace(/
/gi, '
\n'); + } + + result[index] = line; + }); + return result.join('\n'); + }; + + _proto._removeNewlinesBeforeAfterAndBlockElement = function _removeNewlinesBeforeAfterAndBlockElement(markdown) { + // Newlines('\n\n') are created on to-mark. + var NEWLINES_BEFORE_BLOCK_RX = /
\n\n(#{1,6} .*|```|\||(\*+|-+|\d+\.) .*| *>[^\n]+.*)/g; + var NEWLINES_AFTER_BLOCK_RX = /(#{1,6} .*|```|\|)\n\n
/g; + markdown = markdown.replace(NEWLINES_BEFORE_BLOCK_RX, '
$1'); + markdown = markdown.replace(NEWLINES_AFTER_BLOCK_RX, '$1\n
'); + return markdown; + }; + + _proto._appendAttributeForLinkIfNeed = function _appendAttributeForLinkIfNeed(html) { + var LINK_RX = /!?\[.*\]\(<\s*a[^>]*>(.*?)<\s*\/\s*a>\)/gi; + return html.replace(LINK_RX, function (match) { + return match.replace(//gi; + var FIND_DOUBLE_BR_RX = /

/gi; + var FIND_PASSING_AND_NORMAL_BR_RX = /

(.)/gi; + var FIRST_TWO_BRS_BEFORE_RX = /([^>]|<\/a>|<\/code>|<\/span>|<\/b>|<\/i>|<\/s>|]*>)/; + var TWO_BRS_RX = /

/; + var FIND_FIRST_TWO_BRS_RX = new RegExp(FIRST_TWO_BRS_BEFORE_RX.source + TWO_BRS_RX.source, 'g'); + var FIND_ATTRI_WITH_EMTPY_STR_RX = /
/gi; + html = html.replace(FIND_BR_RX, '
'); + html = html.replace(FIND_DOUBLE_BR_RX, '

'); + html = html.replace(FIND_ATTRI_WITH_EMTPY_STR_RX, '
'); + html = html.replace(FIND_PASSING_AND_NORMAL_BR_RX, '

$1'); + html = html.replace(FIND_FIRST_TWO_BRS_RX, '$1

'); // Preserve
when there is only one empty line before or after a block element. + + html = html.replace(/(.)

(|
||
    |
      |
      )/g, '$1

      $2'); + html = html.replace(/(<\/h[1-6]>|<\/pre>|<\/table>|<\/ul>|<\/ol>|<\/blockquote>)
      (.)/g, '$1
      $2'); + return html; + }; + + return Convertor; +}(); + +/* harmony default export */ __webpack_exports__["a"] = (Convertor); + +/***/ }), +/* 38 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/domUtil/css.js +var css = __webpack_require__(4); +var css_default = /*#__PURE__*/__webpack_require__.n(css); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/type/isString.js +var isString = __webpack_require__(9); +var isString_default = /*#__PURE__*/__webpack_require__.n(isString); + +// CONCATENATED MODULE: ./src/js/lazyRunner.js +/** + * @fileoverview Implements LazyRunner + * @author NHN FE Development Lab + */ + +/** + * Class LazyRunner + * @ignore + */ + +var lazyRunner_LazyRunner = /*#__PURE__*/function () { + function LazyRunner() { + this.globalTOID = null; + this.lazyRunFunctions = {}; + } + + var _proto = LazyRunner.prototype; + + _proto.run = function run(fn, params, context, delay) { + var TOID; + + if (isString_default()(fn)) { + TOID = this._runRegisteredRun(fn, params, context, delay); + } else { + TOID = this._runSingleRun(fn, params, context, delay, this.globalTOID); + this.globalTOID = TOID; + } + + return TOID; + }; + + _proto.registerLazyRunFunction = function registerLazyRunFunction(name, fn, delay, context) { + context = context || this; + this.lazyRunFunctions[name] = { + fn: fn, + delay: delay, + context: context, + TOID: null + }; + }; + + _proto._runSingleRun = function _runSingleRun(fn, params, context, delay, TOID) { + this._clearTOIDIfNeed(TOID); + + TOID = setTimeout(function () { + fn.call(context, params); + }, delay); + return TOID; + }; + + _proto._runRegisteredRun = function _runRegisteredRun(lazyRunName, params, context, delay) { + var lazyRunFunction = this.lazyRunFunctions[lazyRunName]; + var fn = lazyRunFunction.fn; + var TOID = lazyRunFunction.TOID; + delay = delay || lazyRunFunction.delay; + context = context || lazyRunFunction.context; + TOID = this._runSingleRun(fn, params, context, delay, TOID); + lazyRunFunction.TOID = TOID; + return TOID; + }; + + _proto._clearTOIDIfNeed = function _clearTOIDIfNeed(TOID) { + if (TOID) { + clearTimeout(TOID); + } + }; + + return LazyRunner; +}(); + +/* harmony default export */ var lazyRunner = (lazyRunner_LazyRunner); +// EXTERNAL MODULE: ./src/js/utils/dom.js +var dom = __webpack_require__(0); + +// EXTERNAL MODULE: ./src/js/codeBlockManager.js +var codeBlockManager = __webpack_require__(30); + +// CONCATENATED MODULE: ./src/js/preview.js +/** + * @fileoverview Implements preview + * @author NHN FE Development Lab + */ + + + + +/** + * Class Preview + * @param {HTMLElement} el - Container element for preview + * @param {EventManager} eventManager - Event manager instance + * @param {Convertor} convertor - Convertor instance + * @param {boolean} isViewer - whether viewer mode or not + * @ignore + */ + +var preview_Preview = /*#__PURE__*/function () { + function Preview(el, eventManager, convertor, isViewer) { + this.eventManager = eventManager; + this.convertor = convertor; + this.el = el; + this.isViewer = !!isViewer; + this.delayCodeBlockTime = 500; + + this._initContentSection(); + + this.lazyRunner = new lazyRunner(); + } + /** + * Initialize content selection + * @private + */ + + + var _proto = Preview.prototype; + + _proto._initContentSection = function _initContentSection() { + this._previewContent = dom["a" /* default */].createElementWith("
      "); + this.el.appendChild(this._previewContent); + }; + + _proto.getCodeBlockElements = function getCodeBlockElements(nodeIds) { + var contentEl = this._previewContent; + var codeEls = []; + var targetEls; + + if (nodeIds) { + targetEls = nodeIds.map(function (id) { + return contentEl.querySelector("[data-nodeid=\"" + id + "\"]"); + }).filter(Boolean); + } else { + targetEls = [contentEl]; + } + + targetEls.forEach(function (targetEl) { + codeEls.push.apply(codeEls, dom["a" /* default */].findAll(targetEl, 'code[data-language]')); + }); + return codeEls; + }; + + _proto.invokeCodeBlockPlugins = function invokeCodeBlockPlugins(codeBlocks) { + codeBlocks.forEach(function (codeBlock) { + var lang = codeBlock.getAttribute('data-language'); + var html = codeBlockManager["a" /* default */].createCodeBlockHtml(lang, codeBlock.textContent); + codeBlock.innerHTML = html; + }); + } + /** + * Refresh rendering + * @param {string} markdown Markdown text + */ + ; + + _proto.refresh = function refresh(markdown) { + if (markdown === void 0) { + markdown = ''; + } + + this.render(this.convertor.toHTMLWithCodeHighlight(markdown)); + this.invokeCodeBlockPlugins(this.getCodeBlockElements()); + } + /** + * get html string + * @returns {string} - html preview string + */ + ; + + _proto.getHTML = function getHTML() { + return this._previewContent.innerHTML; + } + /** + * set html string + * @param {string} html - html preview string + */ + ; + + _proto.setHTML = function setHTML(html) { + this._previewContent.innerHTML = html; + } + /** + * Render HTML on preview + * @param {string} html HTML string + */ + ; + + _proto.render = function render(html) { + var _previewContent = this._previewContent; + html = this.eventManager.emit('previewBeforeHook', html) || html; + dom["a" /* default */].empty(_previewContent); + _previewContent.innerHTML = html; + } + /** + * Set preview height + * @param {number} height - Height for preview container + */ + ; + + _proto.setHeight = function setHeight(height) { + css_default()(this.el, { + height: height + "px" + }); + } + /** + * set min height + * @param {number} minHeight - min height + */ + ; + + _proto.setMinHeight = function setMinHeight(minHeight) { + css_default()(this.el, { + minHeight: minHeight + "px" + }); + } + /** + * Is Preview visible + * @returns {boolean} result + */ + ; + + _proto.isVisible = function isVisible() { + return this.el.style.display !== 'none'; + }; + + return Preview; +}(); + +/* harmony default export */ var preview = __webpack_exports__["a"] = (preview_Preview); + +/***/ }), +/* 39 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Set className value + * @author NHN FE Development Lab + */ + + + +var isArray = __webpack_require__(17); +var isUndefined = __webpack_require__(8); + +/** + * Set className value + * @param {(HTMLElement|SVGElement)} element - target element + * @param {(string|string[])} cssClass - class names + * @private + */ +function setClassName(element, cssClass) { + cssClass = isArray(cssClass) ? cssClass.join(' ') : cssClass; + + cssClass = cssClass.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + + if (isUndefined(element.className.baseVal)) { + element.className = cssClass; + + return; + } + + element.className.baseVal = cssClass; +} + +module.exports = setClassName; + + +/***/ }), +/* 40 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Get event collection for specific HTML element + * @author NHN FE Development Lab + */ + + + +var EVENT_KEY = '_feEventKey'; + +/** + * Get event collection for specific HTML element + * @param {HTMLElement} element - HTML element + * @param {string} type - event type + * @returns {array} + * @private + */ +function safeEvent(element, type) { + var events = element[EVENT_KEY]; + var handlers; + + if (!events) { + events = element[EVENT_KEY] = {}; + } + + handlers = events[type]; + if (!handlers) { + handlers = events[type] = []; + } + + return handlers; +} + +module.exports = safeEvent; + + +/***/ }), +/* 41 */, +/* 42 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is truthy or not. + * @author NHN FE Development Lab + */ + + + +var isExisty = __webpack_require__(28); + +/** + * Check whether the given variable is truthy or not. + * If the given variable is not null or not undefined or not false, returns true. + * (It regards 0 as true) + * @param {*} obj - Target for checking + * @returns {boolean} Is truthy? + * @memberof module:type + */ +function isTruthy(obj) { + return isExisty(obj) && obj !== false; +} + +module.exports = isTruthy; + + +/***/ }), +/* 43 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Send hostname on DOMContentLoaded. + * @author NHN FE Development Lab + */ + + + +var isUndefined = __webpack_require__(8); +var imagePing = __webpack_require__(49); + +var ms7days = 7 * 24 * 60 * 60 * 1000; + +/** + * Check if the date has passed 7 days + * @param {number} date - milliseconds + * @returns {boolean} + * @private + */ +function isExpired(date) { + var now = new Date().getTime(); + + return now - date > ms7days; +} + +/** + * Send hostname on DOMContentLoaded. + * To prevent hostname set tui.usageStatistics to false. + * @param {string} appName - application name + * @param {string} trackingId - GA tracking ID + * @ignore + */ +function sendHostname(appName, trackingId) { + var url = 'https://www.google-analytics.com/collect'; + var hostname = location.hostname; + var hitType = 'event'; + var eventCategory = 'use'; + var applicationKeyForStorage = 'TOAST UI ' + appName + ' for ' + hostname + ': Statistics'; + var date = window.localStorage.getItem(applicationKeyForStorage); + + // skip if the flag is defined and is set to false explicitly + if (!isUndefined(window.tui) && window.tui.usageStatistics === false) { + return; + } + + // skip if not pass seven days old + if (date && !isExpired(date)) { + return; + } + + window.localStorage.setItem(applicationKeyForStorage, new Date().getTime()); + + setTimeout(function() { + if (document.readyState === 'interactive' || document.readyState === 'complete') { + imagePing(url, { + v: 1, + t: hitType, + tid: trackingId, + cid: hostname, + dp: hostname, + dh: appName, + el: appName, + ec: eventCategory + }); + } + }, 1000); +} + +module.exports = sendHostname; + + +/***/ }), +/* 44 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is falsy or not. + * @author NHN FE Development Lab + */ + + + +var isTruthy = __webpack_require__(42); + +/** + * Check whether the given variable is falsy or not. + * If the given variable is null or undefined or false, returns true. + * @param {*} obj - Target for checking + * @returns {boolean} Is falsy? + * @memberof module:type + */ +function isFalsy(obj) { + return !isTruthy(obj); +} + +module.exports = isFalsy; + + +/***/ }), +/* 45 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview This module provides a Enum Constructor. + * @author NHN FE Development Lab + * @example + * // node, commonjs + * var Enum = require('tui-code-snippet/enum/enum'); + */ + + + +var isNumber = __webpack_require__(34); +var isArray = __webpack_require__(17); +var toArray = __webpack_require__(3); +var forEach = __webpack_require__(26); + +/** + * Check whether the defineProperty() method is supported. + * @type {boolean} + * @ignore + */ +var isSupportDefinedProperty = (function() { + try { + Object.defineProperty({}, 'x', {}); + + return true; + } catch (e) { + return false; + } +})(); + +/** + * A unique value of a constant. + * @type {number} + * @ignore + */ +var enumValue = 0; + +/** + * Make a constant-list that has unique values. + * In modern browsers (except IE8 and lower), + * a value defined once can not be changed. + * + * @param {...string|string[]} itemList Constant-list (An array of string is available) + * @class + * + * @example + * var Enum = require('tui-code-snippet/enum/enum'); // node, commonjs + * + * var MYENUM = new Enum('TYPE1', 'TYPE2'); + * var MYENUM2 = new Enum(['TYPE1', 'TYPE2']); + * + * //usage + * if (value === MYENUM.TYPE1) { + * .... + * } + * + * //add (If a duplicate name is inputted, will be disregarded.) + * MYENUM.set('TYPE3', 'TYPE4'); + * + * //get name of a constant by a value + * MYENUM.getName(MYENUM.TYPE1); // 'TYPE1' + * + * // In modern browsers (except IE8 and lower), a value can not be changed in constants. + * var originalValue = MYENUM.TYPE1; + * MYENUM.TYPE1 = 1234; // maybe TypeError + * MYENUM.TYPE1 === originalValue; // true + **/ +function Enum(itemList) { + if (itemList) { + this.set.apply(this, arguments); + } +} + +/** + * Define a constants-list + * @param {...string|string[]} itemList Constant-list (An array of string is available) + */ +Enum.prototype.set = function(itemList) { + var self = this; + + if (!isArray(itemList)) { + itemList = toArray(arguments); + } + + forEach(itemList, function itemListIteratee(item) { + self._addItem(item); + }); +}; + +/** + * Return a key of the constant. + * @param {number} value A value of the constant. + * @returns {string|undefined} Key of the constant. + */ +Enum.prototype.getName = function(value) { + var self = this; + var foundedKey; + + forEach(this, function(itemValue, key) { // eslint-disable-line consistent-return + if (self._isEnumItem(key) && value === itemValue) { + foundedKey = key; + + return false; + } + }); + + return foundedKey; +}; + +/** + * Create a constant. + * @private + * @param {string} name Constant name. (It will be a key of a constant) + */ +Enum.prototype._addItem = function(name) { + var value; + + if (!this.hasOwnProperty(name)) { + value = this._makeEnumValue(); + + if (isSupportDefinedProperty) { + Object.defineProperty(this, name, { + enumerable: true, + configurable: false, + writable: false, + value: value + }); + } else { + this[name] = value; + } + } +}; + +/** + * Return a unique value for assigning to a constant. + * @private + * @returns {number} A unique value + */ +Enum.prototype._makeEnumValue = function() { + var value; + + value = enumValue; + enumValue += 1; + + return value; +}; + +/** + * Return whether a constant from the given key is in instance or not. + * @param {string} key - A constant key + * @returns {boolean} Result + * @private + */ +Enum.prototype._isEnumItem = function(key) { + return isNumber(this[key]); +}; + +module.exports = Enum; + + +/***/ }), +/* 46 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_object_extend__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7); +/* harmony import */ var tui_code_snippet_object_extend__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_object_extend__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(19); +/* harmony import */ var tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(20); +/* harmony import */ var tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _mdPreview__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(35); +/* harmony import */ var _eventManager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(36); +/* harmony import */ var _commandManager__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1); +/* harmony import */ var _convertor__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(37); +/* harmony import */ var _utils_dom__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(0); +/* harmony import */ var _codeBlockManager__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(30); +/* harmony import */ var _pluginHelper__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(31); +/* harmony import */ var _utils_common__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(12); +/* harmony import */ var _htmlSanitizer__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(25); +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +/** + * @fileoverview Implements editor preivew + * @author NHN FE Development Lab + */ + + + + + + + + + + + + + +var TASK_ATTR_NAME = 'data-te-task'; +var DISABLED_TASK_ATTR_NAME = 'data-te-task-disabled'; +var TASK_CHECKED_CLASS_NAME = 'checked'; +/** + * Class ToastUIEditorViewer + * @param {object} options Option object + * @param {HTMLElement} options.el - container element + * @param {string} [options.initialValue] Editor's initial value + * @param {Object} [options.events] - Events + * @param {function} [options.events.load] - It would be emitted when editor fully load + * @param {function} [options.events.change] - It would be emitted when content changed + * @param {function} [options.events.stateChange] - It would be emitted when format change by cursor position + * @param {function} [options.events.focus] - It would be emitted when editor get focus + * @param {function} [options.events.blur] - It would be emitted when editor loose focus + * @param {Object} [options.hooks] - Hooks + * @param {function} [options.hooks.previewBeforeHook] - Submit preview to hook URL before preview be shown + * @param {Array.} [options.plugins] - Array of plugins. A plugin can be either a function or an array in the form of [function, options]. + * @param {boolean} [options.useDefaultHTMLSanitizer=true] - use default htmlSanitizer + * @param {Object} [options.extendedAutolinks] - Using extended Autolinks specified in GFM spec + * @param {Object} [options.customConvertor] - convertor extention + * @param {Object} [options.linkAttribute] - Attributes of anchor element that should be rel, target, contenteditable, hreflang, type + * @param {Object} [options.customHTMLRenderer] - Object containing custom renderer functions correspond to markdown node + * @param {boolean} [options.referenceDefinition=false] - whether use the specification of link reference definition + * @param {function} [options.customHTMLSanitizer=null] - custom HTML sanitizer + * @param {boolean} [options.frontMatter=false] - whether use the front matter + */ + +var ToastUIEditorViewer = /*#__PURE__*/function () { + function ToastUIEditorViewer(options) { + var _this = this; + + this.options = tui_code_snippet_object_extend__WEBPACK_IMPORTED_MODULE_1___default()({ + useDefaultHTMLSanitizer: true, + linkAttribute: null, + extendedAutolinks: false, + customConvertor: null, + customHTMLRenderer: null, + referenceDefinition: false, + customHTMLSanitizer: null, + frontMatter: false + }, options); + this.codeBlockLanguages = []; + this.eventManager = new _eventManager__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"](); + this.commandManager = new _commandManager__WEBPACK_IMPORTED_MODULE_6__[/* default */ "a"](this); + var linkAttribute = Object(_utils_common__WEBPACK_IMPORTED_MODULE_11__[/* sanitizeLinkAttribute */ "c"])(this.options.linkAttribute); + + var _getPluginInfo = Object(_pluginHelper__WEBPACK_IMPORTED_MODULE_10__[/* getPluginInfo */ "a"])(this.options.plugins), + renderer = _getPluginInfo.renderer, + parser = _getPluginInfo.parser, + plugins = _getPluginInfo.plugins; + + var _this$options = this.options, + customHTMLRenderer = _this$options.customHTMLRenderer, + customHTMLSanitizer = _this$options.customHTMLSanitizer, + extendedAutolinks = _this$options.extendedAutolinks, + referenceDefinition = _this$options.referenceDefinition, + frontMatter = _this$options.frontMatter; + var rendererOptions = { + linkAttribute: linkAttribute, + customHTMLRenderer: _extends({}, renderer, customHTMLRenderer), + extendedAutolinks: extendedAutolinks, + referenceDefinition: referenceDefinition, + customParser: parser, + frontMatter: frontMatter + }; + + if (this.options.customConvertor) { + // eslint-disable-next-line new-cap + this.convertor = new this.options.customConvertor(this.eventManager, rendererOptions); + } else { + this.convertor = new _convertor__WEBPACK_IMPORTED_MODULE_7__[/* default */ "a"](this.eventManager, rendererOptions); + } + + var sanitizer = customHTMLSanitizer || (this.options.useDefaultHTMLSanitizer ? _htmlSanitizer__WEBPACK_IMPORTED_MODULE_12__[/* default */ "a"] : null); + + if (sanitizer) { + this.convertor.initHtmlSanitizer(sanitizer); + } + + if (this.options.hooks) { + tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default()(this.options.hooks, function (fn, key) { + _this.addHook(key, fn); + }); + } + + if (this.options.events) { + tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default()(this.options.events, function (fn, key) { + _this.on(key, fn); + }); + } + + var _this$options2 = this.options, + el = _this$options2.el, + initialValue = _this$options2.initialValue; + var existingHTML = el.innerHTML; + el.innerHTML = ''; + this.preview = new _mdPreview__WEBPACK_IMPORTED_MODULE_4__[/* default */ "a"](el, this.eventManager, this.convertor, _extends({}, rendererOptions, { + isViewer: true + })); + tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_2___default()(this.preview.el, 'mousedown', this._toggleTask.bind(this)); + + if (plugins) { + Object(_pluginHelper__WEBPACK_IMPORTED_MODULE_10__[/* invokePlugins */ "b"])(plugins, this); + } + + if (initialValue) { + this.setMarkdown(initialValue); + } else if (existingHTML) { + this.preview.setHTML(existingHTML); + } + + this.eventManager.emit('load', this); + } + /** + * Toggle task by detecting mousedown event. + * @param {MouseEvent} ev - event + * @private + */ + + + var _proto = ToastUIEditorViewer.prototype; + + _proto._toggleTask = function _toggleTask(ev) { + var style = getComputedStyle(ev.target, ':before'); + + if (!ev.target.hasAttribute(DISABLED_TASK_ATTR_NAME) && ev.target.hasAttribute(TASK_ATTR_NAME) && _utils_dom__WEBPACK_IMPORTED_MODULE_8__[/* default */ "a"].isInsideButtonBox(style, ev.offsetX, ev.offsetY)) { + _utils_dom__WEBPACK_IMPORTED_MODULE_8__[/* default */ "a"].toggleClass(ev.target, TASK_CHECKED_CLASS_NAME); + this.eventManager.emit('change', { + source: 'viewer', + data: ev + }); + } + } + /** + * Set content for preview + * @param {string} markdown Markdown text + */ + ; + + _proto.setMarkdown = function setMarkdown(markdown) { + this.markdownValue = markdown = markdown || ''; + this.preview.refresh(this.markdownValue); + this.eventManager.emit('setMarkdownAfter', this.markdownValue); + } + /** + * Bind eventHandler to event type + * @param {string} type Event type + * @param {function} handler Event handler + */ + ; + + _proto.on = function on(type, handler) { + this.eventManager.listen(type, handler); + } + /** + * Unbind eventHandler from event type + * @param {string} type Event type + */ + ; + + _proto.off = function off(type) { + this.eventManager.removeEventHandler(type); + } + /** + * Remove Viewer preview from document + */ + ; + + _proto.remove = function remove() { + this.eventManager.emit('removeEditor'); + tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_3___default()(this.preview.el, 'mousedown', this._toggleTask.bind(this)); + this.preview.remove(); + this.options = null; + this.eventManager = null; + this.commandManager = null; + this.convertor = null; + this.preview = null; + } + /** + * Add hook to Viewer preview's event + * @param {string} type Event type + * @param {function} handler Event handler + */ + ; + + _proto.addHook = function addHook(type, handler) { + this.eventManager.removeEventHandler(type); + this.eventManager.listen(type, handler); + } + /** + * Return true + * @returns {boolean} + */ + ; + + _proto.isViewer = function isViewer() { + return true; + } + /** + * Return false + * @returns {boolean} + */ + ; + + _proto.isMarkdownMode = function isMarkdownMode() { + return false; + } + /** + * Return false + * @returns {boolean} + */ + ; + + _proto.isWysiwygMode = function isWysiwygMode() { + return false; + } + /** + * Set code block languages + * @param {Array} languages - code lauguage list + */ + ; + + _proto.setCodeBlockLanguages = function setCodeBlockLanguages(languages) { + var _this2 = this; + + if (languages === void 0) { + languages = []; + } + + languages.forEach(function (lang) { + if (_this2.codeBlockLanguages.indexOf(lang) < 0) { + _this2.codeBlockLanguages.push(lang); + } + }); + }; + + return ToastUIEditorViewer; +}(); +/** + * Check whether is viewer (using in plugins) + * @type {boolean} + * @ignore + */ + + +ToastUIEditorViewer.isViewer = true; +/** + * domUtil instance + * @type {DomUtil} + * @ignore + */ + +ToastUIEditorViewer.domUtils = _utils_dom__WEBPACK_IMPORTED_MODULE_8__[/* default */ "a"]; +/** + * CodeBlockManager instance using in plugins + * @type {CodeBlockManager} + * @ignore + */ + +ToastUIEditorViewer.codeBlockManager = _codeBlockManager__WEBPACK_IMPORTED_MODULE_9__[/* default */ "a"]; +/** + * WwCodeBlockManager class using in plugins + * @type {Class.} + * @ignore + */ + +ToastUIEditorViewer.WwCodeBlockManager = null; +/** + * WwTableManager class using in plugins + * @type {Class.} + * @ignore + */ + +ToastUIEditorViewer.WwTableManager = null; +/** + * WwTableManager class using in plugins + * @type {Class.} + * @ignore + */ + +ToastUIEditorViewer.WwTableSelectionManager = null; +/* harmony default export */ __webpack_exports__["a"] = (ToastUIEditorViewer); + +/***/ }), +/* 47 */, +/* 48 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is null or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is null or not. + * If the given variable(arguments[0]) is null, returns true. + * @param {*} obj - Target for checking + * @returns {boolean} Is null? + * @memberof module:type + */ +function isNull(obj) { + return obj === null; +} + +module.exports = isNull; + + +/***/ }), +/* 49 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Request image ping. + * @author NHN FE Development Lab + */ + + + +var forEachOwnProperties = __webpack_require__(10); + +/** + * @module request + */ + +/** + * Request image ping. + * @param {String} url url for ping request + * @param {Object} trackingInfo infos for make query string + * @returns {HTMLElement} + * @memberof module:request + * @example + * var imagePing = require('tui-code-snippet/request/imagePing'); // node, commonjs + * + * imagePing('https://www.google-analytics.com/collect', { + * v: 1, + * t: 'event', + * tid: 'trackingid', + * cid: 'cid', + * dp: 'dp', + * dh: 'dh' + * }); + */ +function imagePing(url, trackingInfo) { + var trackingElement = document.createElement('img'); + var queryString = ''; + forEachOwnProperties(trackingInfo, function(value, key) { + queryString += '&' + key + '=' + value; + }); + queryString = queryString.substring(1); + + trackingElement.src = url + '?' + queryString; + + trackingElement.style.display = 'none'; + document.body.appendChild(trackingElement); + document.body.removeChild(trackingElement); + + return trackingElement; +} + +module.exports = imagePing; + + +/***/ }), +/* 50 */, +/* 51 */ +/***/ (function(module, exports, __webpack_require__) { + +// extracted by mini-css-extract-plugin + +/***/ }), +/* 52 */, +/* 53 */, +/* 54 */, +/* 55 */, +/* 56 */, +/* 57 */, +/* 58 */, +/* 59 */, +/* 60 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _viewer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(46); +/* harmony import */ var _css_contents_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(51); +/* harmony import */ var _css_contents_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_css_contents_css__WEBPACK_IMPORTED_MODULE_1__); +/** + * @fileoverview entry point for viewer + * @author NHN FE Development Lab + */ + + +/* harmony default export */ __webpack_exports__["default"] = (_viewer__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"]); + +/***/ }) +/******/ ])["default"]; +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor.css b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor.css new file mode 100644 index 0000000000..2cee463091 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor.css @@ -0,0 +1,1804 @@ +/*! + * @toast-ui/editor + * @version 2.5.1 | Tue Nov 24 2020 + * @author NHN FE Development Lab + * @license MIT + */ +@charset "utf-8"; +/* height */ +.auto-height, +.auto-height .tui-editor-defaultUI { + height: auto; +} + +.auto-height .tui-editor { + position: relative; +} + +:not(.auto-height) > .tui-editor-defaultUI, +:not(.auto-height) > .tui-editor-defaultUI > .te-editor-section { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; +} + +:not(.auto-height) > .tui-editor-defaultUI > .te-editor-section { + -ms-flex: 1; + flex: 1; +} + +/* tui editor */ +.tui-editor:after, +.tui-editor-defaultUI-toolbar:after { + content: ''; + display: block; + height: 0; + clear: both; +} + +.tui-editor { + position: absolute; + line-height: 1; + color: #222; + width: 100%; + height: inherit; +} + +.te-editor-section { + min-height: 0px; + position: relative; + height: inherit; +} + +.te-md-container { + display: none; + overflow: hidden; + height: 100%; +} + +.te-md-container .te-editor { + line-height: 1.5; +} + +.te-md-container .te-editor, +.te-md-container .te-preview { + box-sizing: border-box; + padding: 0; + height: inherit; +} + +.te-md-container .CodeMirror { + font-size: 13px; + height: inherit; +} + +.te-md-container .te-preview { + overflow: auto; + padding: 0 25px; + height: 100%; +} + +.te-md-container .te-preview > p:first-child { + margin-top: 0 !important; +} + +.te-md-container .te-preview .tui-editor-contents { + padding-top: 8px; +} + +.tui-editor .te-preview-style-tab > .te-editor, +.tui-editor .te-preview-style-tab > .te-preview { + float: left; + width: 100%; + display: none; +} + +.tui-editor .te-preview-style-tab > .te-tab-active { + display: block; +} + +.tui-editor .te-preview-style-vertical > .te-tab-section { + display: none; +} + +.tui-editor .te-preview-style-tab > .te-tab-section { + display: block; +} + +.tui-editor .te-preview-style-vertical .te-editor { + float: left; + width: 50%; +} + +.tui-editor .te-preview-style-vertical .te-preview { + float: left; + width: 50%; +} + +.tui-editor .te-md-splitter { + display: none; + position: absolute; + left: 50%; + top: 0; + height: 100%; + width: 1px; + border-left: 1px solid #e5e5e5; +} + +.tui-editor .te-preview-style-vertical .te-md-splitter { + display: block; +} + +.te-ww-container { + display: none; + overflow: hidden; + z-index: 10; + height: inherit; + background-color: #fff; +} + +.te-ww-container > .te-editor { + overflow: auto; + height: inherit; +} + +.te-ww-container .tui-editor-contents:focus { + outline: none; +} + +.te-ww-container .tui-editor-contents { + padding: 0 25px; +} + +.te-ww-container .tui-editor-contents:first-child { + box-sizing: border-box; + margin: 0px; + padding: 16px 25px 0px 25px; + height: inherit; +} + +.te-ww-container .tui-editor-contents:last-child { + margin-bottom: 16px; +} + +.te-md-mode .te-md-container { + display: block; + z-index: 100; +} + +.te-ww-mode .te-ww-container { + display: block; + z-index: 100; +} + +.tui-editor.te-hide, +.tui-editor-defaultUI.te-hide { + display: none; +} + +.tui-editor-defaultUI .CodeMirror-lines { + padding-top: 18px; + padding-bottom: 18px; +} + +.tui-editor-defaultUI pre.CodeMirror-line { + padding-left: 25px; + padding-right: 25px; +} + +.tui-editor-defaultUI .CodeMirror pre.CodeMirror-placeholder { + margin: 0; + padding-left: 25px; + color: grey; +} + +.tui-editor-defaultUI .CodeMirror-scroll { + cursor: text; +} + +/* Essential element style */ +.tui-editor-contents td.te-cell-selected { + background-color: #d8dfec; +} +.tui-editor-contents td.te-cell-selected::selection { + background-color: #d8dfec; +} +.tui-editor-contents th.te-cell-selected { + background-color: #908f8f; +} +.tui-editor-contents th.te-cell-selected::selection { + background-color: #908f8f; +} + +/* default UI Styles */ +.tui-editor-defaultUI { + position: relative; + border: 1px solid #e5e5e5; + height: 100%; + font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', 'Arial', '나눔바른고딕', + 'Nanum Barun Gothic', '맑은고딕', 'Malgun Gothic', sans-serif; +} + +.tui-editor-defaultUI button { + color: #fff; + padding: 0px 14px 0px 15px; + height: 28px; + font-size: 12px; + border: none; + cursor: pointer; + outline: none; +} +.tui-editor-defaultUI button.te-ok-button { + background-color: #4b96e6; +} +.tui-editor-defaultUI button.te-close-button { + background-color: #777; +} + +.tui-editor-defaultUI-toolbar { + padding: 0 25px; + height: 31px; + background-color: #fff; + border: 0; + overflow: hidden; +} + +.tui-toolbar-divider { + float: left; + display: inline-block; + width: 1px; + height: 14px; + background-color: #ddd; + margin: 9px 6px; +} + +.tui-toolbar-button-group { + height: 28px; + border-right: 1px solid #d9d9d9; + float: left; +} + +.te-toolbar-section { + height: 32px; + box-sizing: border-box; + border-bottom: 1px solid #e5e5e5; +} + +.tui-editor-defaultUI-toolbar button { + float: left; + box-sizing: border-box; + outline: none; + cursor: pointer; + background-color: #fff; + width: 22px; + height: 22px; + padding: 3px; + border-radius: 0; + margin: 5px 3px; + border: 1px solid #fff; +} + +.tui-editor-defaultUI-toolbar button:hover, +.tui-editor-defaultUI-toolbar button:active, +.tui-editor-defaultUI-toolbar button.active { + border: 1px solid #aaa; + background-color: #fff; +} + +.tui-editor-defaultUI-toolbar button:first-child { + margin-left: 0; +} + +.tui-editor-defaultUI-toolbar button:last-child { + margin-right: 0; +} + +.tui-editor-defaultUI-toolbar button.tui-scrollsync { + width: auto; + color: #777777; + border: 0; +} + +.tui-editor-defaultUI button.tui-scrollsync:after { + content: 'Scroll off'; +} + +.tui-editor-defaultUI button.tui-scrollsync.active { + color: #4b96e6; + font-weight: bold; +} + +.tui-editor-defaultUI button.tui-scrollsync.active:after { + content: 'Scroll on'; +} + +.tui-editor-defaultUI .te-mode-switch-section { + background-color: #f9f9f9; + border-top: 1px solid #e5e5e5; + height: 20px; + font-size: 12px; +} + +.tui-editor-defaultUI .te-mode-switch { + float: right; + height: 100%; +} + +.tui-editor-defaultUI .te-switch-button { + width: 92px; + height: inherit; + background: #e5e5e5; + outline: 0; + color: #a0aabf; + cursor: pointer; + border: 0; + border-left: 1px solid #ddd; + border-right: 1px solid #ddd; +} + +.tui-editor-defaultUI .te-switch-button.active { + background-color: #fff; + color: #000; +} + +.tui-editor-defaultUI .te-markdown-tab-section { + float: left; + height: 31px; + background: #fff; +} + +.te-markdown-tab-section .te-tab { + margin: 0 -7px 0 24px; + background: #fff; +} + +.tui-editor-defaultUI .te-tab button { + box-sizing: border-box; + line-height: 100%; + position: relative; + cursor: pointer; + z-index: 1; + font-size: 13px; + background-color: #f9f9f9; + border: solid 1px #e5e5e5; + border-top: 0; + padding: 0 9px; + color: #777; + border-radius: 0; + outline: 0; +} + +.te-markdown-tab-section .te-tab button:last-child { + margin-left: -1px; +} + +.te-markdown-tab-section .te-tab button.te-tab-active, +.te-markdown-tab-section .te-tab button:hover.te-tab-active { + background-color: #fff; + color: #333; + border-bottom: 1px solid #fff; + z-index: 2; +} + +.te-markdown-tab-section .te-tab button:hover { + background-color: #fff; + color: #333; +} + +.tui-popup-modal-background { + background-color: rgba(202, 202, 202, 0.6); + position: fixed; + margin: 0px; + left: 0px; + top: 0px; + width: 100%; + height: 100%; + z-index: 9999; +} + +.tui-popup-wrapper.fit-window, +.tui-popup-modal-background.fit-window .tui-popup-wrapper { + width: 100%; + height: 100%; +} + +.tui-popup-wrapper { + width: 500px; + margin-right: auto; + border: 1px solid #cacaca; + background: white; + z-index: 9999; +} + +.tui-popup-modal-background .tui-popup-wrapper { + position: absolute; + margin: auto; + top: 0px; + right: 0px; + bottom: 0px; + left: 0px; +} + +.tui-popup-header { + padding: 10px; + height: auto; + line-height: normal; + position: relative; + border-bottom: 1px solid #cacaca; +} + +.tui-popup-header .tui-popup-header-buttons { + float: right; +} + +.tui-popup-header .tui-popup-header-buttons button { + padding: 0px; + background-color: transparent; + background-size: cover; + float: left; +} + +.tui-popup-header .tui-popup-close-button { + margin: 3px; + width: 13px; + height: 13px; + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxMHB4IiBoZWlnaHQ9IjEwcHgiIHZpZXdCb3g9IjAgMCAxMCAxMCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT5GMjc2Qzc4MC0zM0JBLTQ3MTItQTM3OC04RkQwQUNDOTFDRTk8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImxuYi1mb2xkZXItZGVsIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGZpbGw9IiM3Nzc3NzciPiAgICAgICAgICAgIDxwYXRoIGQ9Ik01LDMuNTg1Nzg2NDQgTDEuNzA3MTA2NzgsMC4yOTI4OTMyMTkgTDAuMjkyODkzMjE5LDEuNzA3MTA2NzggTDMuNTg1Nzg2NDQsNSBMMC4yOTI4OTMyMTksOC4yOTI4OTMyMiBMMS43MDcxMDY3OCw5LjcwNzEwNjc4IEw1LDYuNDE0MjEzNTYgTDguMjkyODkzMjIsOS43MDcxMDY3OCBMOS43MDcxMDY3OCw4LjI5Mjg5MzIyIEw2LjQxNDIxMzU2LDUgTDkuNzA3MTA2NzgsMS43MDcxMDY3OCBMOC4yOTI4OTMyMiwwLjI5Mjg5MzIxOSBMNSwzLjU4NTc4NjQ0IFoiIGlkPSJDb21iaW5lZC1TaGFwZSI+PC9wYXRoPiAgICAgICAgPC9nPiAgICA8L2c+PC9zdmc+); +} + +.tui-popup-header .tui-popup-title { + font-size: 13px; + font-weight: bold; + color: #333; + vertical-align: bottom; +} + +.tui-popup-body { + padding: 15px; + font-size: 12px; +} + +.tui-editor-popup { + position: absolute; + top: 30px; + left: 50%; + margin-left: -250px; +} + +.tui-editor-popup.tui-popup-modal-background { + position: fixed; + top: 0px; + left: 0px; + margin: 0px; +} + +.tui-editor-popup .tui-popup-body label { + font-weight: bold; + color: #666; + display: block; + margin: 10px 0 5px; +} + +.tui-editor-popup .tui-popup-body .te-button-section { + margin-top: 15px; +} + +.tui-editor-popup .tui-popup-body input[type='text'], +.tui-editor-popup .tui-popup-body input[type='file'] { + padding: 4px 10px; + border: 1px solid #bfbfbf; + box-sizing: border-box; + width: 100%; +} + +.tui-editor-popup .tui-popup-body input[type='text'].disabled { + border-color: #e5e5e5; + background-color: #eee; + color: #e5e5e5; +} + +.tui-editor-popup .tui-popup-body input.wrong { + border-color: #ff0000; +} + +.te-popup-add-link .tui-popup-wrapper { + height: 219px; +} + +.te-popup-add-image .tui-popup-wrapper { + height: 243px; +} + +.te-popup-add-image .te-tab { + display: block; + background: none; + border-bottom: 1px solid #ebebeb; + margin-bottom: 8px; +} + +.te-popup-add-image .te-url-type { + display: none; +} + +.te-popup-add-image .te-file-type { + display: none; +} + +.te-popup-add-image div.te-tab-active, +.te-popup-add-image form.te-tab-active { + display: block; +} + +.te-popup-add-image .te-tab button { + border: 1px solid #ccc; + background: #eee; + min-width: 100px; + margin-left: -1px; + border-bottom: 0px; + border-radius: 3px 3px 0px 0px; +} + +.te-popup-add-image .te-tab button.te-tab-active { + background: #fff; +} + +.te-popup-add-table .te-table-selection { + position: relative; +} + +.te-popup-add-table .te-table-body { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAARCAYAAAAougcOAAAC7mlDQ1BJQ0MgUHJvZmlsZQAAeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFkifEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UXAeIuJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOklEQVQ4EWO8e/fuPwYGBkYgphlgAZmspKREMwtABjPR1HSo4aOWkBTKo8E1GlwkhQBJikdT1wgNLgAMSwQgckFvTgAAAABJRU5ErkJggg=='); +} + +.te-popup-add-table .te-table-header { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAARCAYAAAAougcOAAAC7mlDQ1BJQ0MgUHJvZmlsZQAAeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFkifEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UXAeIuJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAOklEQVQ4EWO8e/fuPwYGBkYgphlgAZksLCxMMwtABjPR1HSo4aOWkBTKo8E1GlwkhQBJikdT1wgNLgDxKwPzTeWPdAAAAABJRU5ErkJggg=='); +} + +.te-popup-add-table .te-selection-area { + position: absolute; + top: 0; + left: 0; + background: #80d2ff; + opacity: 0.3; + z-index: 999; +} + +.te-popup-add-table .te-description { + margin: 10px 0 0 0; + text-align: center; +} + +.te-popup-table-utils { + width: auto; + min-width: 120px; +} + +.te-popup-table-utils .tui-popup-body { + padding: 0px; +} + +.te-popup-table-utils button { + display: block; + width: 100%; + background-color: #fff; + border: none; + outline: 0; + padding: 0px 10px 0px 10px; + font-size: 12px; + line-height: 28px; + text-align: left; + color: #777; +} + +.te-popup-table-utils button:hover { + background-color: #f4f4f4; +} + +.te-popup-table-utils hr { + margin: 0; + background-color: #cacaca; + border-style: none; + height: 1px; +} + +.te-popup-table-utils .te-context-menu-disabled { + color: #ccc; +} + +.te-popup-table-utils .te-context-menu-disabled:hover { + background-color: #fff; +} + +.te-heading-add { + width: auto; +} + +.te-heading-add .tui-popup-body { + padding: 0; +} + +.te-heading-add h1, +.te-heading-add h2, +.te-heading-add h3, +.te-heading-add h4, +.te-heading-add h5, +.te-heading-add h6, +.te-heading-add ul, +.te-heading-add p { + padding: 0; + margin: 0; +} + +.te-heading-add ul { + list-style: none; +} + +.te-heading-add ul li { + padding: 2px 10px; + cursor: pointer; +} + +.te-heading-add ul li:hover { + background-color: #eee; +} + +.te-heading-add h1 { + font-size: 24px; +} + +.te-heading-add h2 { + font-size: 22px; +} + +.te-heading-add h3 { + font-size: 20px; +} + +.te-heading-add h4 { + font-size: 18px; +} + +.te-heading-add h5 { + font-size: 16px; +} + +.te-heading-add h6 { + font-size: 14px; +} + +.te-dropdown-toolbar { + position: absolute; + width: auto; +} + +.te-dropdown-toolbar .tui-popup-body { + padding: 0px; +} + +.tui-popup-color { + padding: 0; +} + +.tui-popup-color .tui-colorpicker-container, +.tui-popup-color .tui-colorpicker-palette-container { + width: 144px; +} + +.tui-popup-color .tui-colorpicker-container ul { + width: 144px; + margin-bottom: 8px; +} + +.tui-popup-color .tui-colorpicker-container li { + padding: 0 1px 1px 0; +} + +.tui-popup-color .tui-colorpicker-container li .tui-colorpicker-palette-button { + border: 0; + width: 17px; + height: 17px; +} + +.tui-popup-color .tui-popup-body { + padding: 10px; +} + +.tui-popup-color .tui-colorpicker-container .tui-colorpicker-palette-toggle-slider { + display: none; +} + +.tui-popup-color .te-apply-button, +.tui-popup-color .tui-colorpicker-palette-hex { + float: right; +} + +.tui-popup-color .te-apply-button { + height: 21px; + width: 35px; + background: #fff; + border: 1px solid #efefef; + position: absolute; + bottom: 135px; + right: 10px; + color: black; +} + +.tui-popup-color .tui-colorpicker-container .tui-colorpicker-palette-hex { + border: 1px solid #e1e1e1; + padding: 3px 14px; + margin-left: -1px; +} + +.tui-popup-color .tui-colorpicker-container div.tui-colorpicker-clearfix { + display: inline-block; +} + +.tui-popup-color .tui-colorpicker-container .tui-colorpicker-palette-preview { + width: 19px; + height: 19px; +} + +.tui-popup-color .tui-colorpicker-slider-container .tui-colorpicker-slider-right { + width: 22px; +} + +.tui-popup-color .tui-colorpicker-slider-container .tui-colorpicker-huebar-handle { + display: none; +} + +.tui-tooltip { + position: absolute; + background-color: #222; + z-index: 999; + opacity: 0.8; + color: #fff; + padding: 2px 5px; + font-size: 10px; +} + +.tui-tooltip .arrow { + content: ''; + display: inline-block; + width: 10px; + height: 10px; + background-color: #222; + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); + position: absolute; + top: -3px; + left: 6px; + z-index: -1; +} + +.tui-toolbar-icons { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANoAAAC8CAYAAAAesLCcAAAAAXNSR0IArs4c6QAAKj9JREFUeAHtnQuUVdWZ5++tgoLi/ZKX8hAVEYIxOmrSyyQkxkw7ziTjGF8QEZwZTEaxO3bjMt29IumVLG1Nxplga0JmIQ8FxTgTk3bF6bQr2Cur07aNOhIVUUAEoajiafEoiqLu/P6Hs2/OPZxzzzn3XqSq+PZap/be3/72d77zP/vb3977nr0rl7NgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAicAgTyae95/fXXF2J434N+0zPPPLM2pjySjLxLogrq6uqONDQ0bF6xYsXBqPI4mtMPPbxncvk4fscXV+70c8/l8nH8ji+u3NGT9HJ8Lk6rp+NPinuansHnBdsG8ot4xtuD9ErTCxcurNuwYcO4lStXbqlUhqtX5xJVxOdS99Eq6pdU7ezs7NPe3j6+hGgZQyABga9//etjYFnDNS+BNVXxvHnzer/zzjuTjx49OiJVhQSmijza6NGj+zY3N1+LUayS/Hw+f3D16tUDEu5VUhz0ENOmTXvtzTffHALD2WKqr6/vfOqpp14rqWCZjxUB53lTeFRvpJOCzxvBJHlU1y6S+IJgUOcz5J/lkrEpHOP6kOvXXIuR9S/EqQPyBvTq1WtSR0dH70Cldtpla+/evVuyjrYkoxYeLVcoFN4IKFR1EsM9XLUQE1AzBG644YbnddVK4MyZM8/TVQt5GIU82BouZ2QSW8+lUdF/5vondL+DOFVA3hlMXyaHjEx1G44dOza8ra1tyi233DIylbAAU69AOnWyqampLcS8MpTPlMWbfSpYgd5kTzCfJg1AJT2ry8fVzdoDIy9yTunkp+2Bq9XL3c/FtdLLyYuL6Uw9fGm0C0m+z/MujeNNQ2dI5sm76aabxtKxtq9atWpXmnoV8NSj7yPc5zVGSf9UQf0TqmBs48D9EBgcOKEwhlATj4bsRdz4ezH3yEz2H+TMzBWtwklBgGnBNTSqf+8b2X3c5G9531MrvRmLC+8i7z0ZGV5iDIaghttYiTzkLKbeDK4dgfqtpFu4NIT0AtOcBS5dLkZeC7wb6OyPOj5NZfByHS6vmPyoYD4pXZFHQ5n8rFmzzmLRQnO0K/ybfJP4r5JuGFWOvLUA3UCZ5mhurncGaY2zUwXpFGQM54NladLSKcgXzgfLsqSr1St8r1rpFZYbzgeMTEX9uJ5hweDSvXv3hllT5Z2RiRljq9OciFW+txndpKofZAKD37EYcsmRI0c0T/sM+UEqR14v5P07kou4vihamkD9Azzb262trecwhOzv1gvoEPJz584dfPDgwXF4Ye8eaeSJp2KPBjglDRtZ7WlvmoaPHsMbWqThNZ6Ti0DIyNzNpu7bt6+i1eagkTlhNOi+69evr3i1+YknnpBHm8ElD+cFDK0Do/kFmSsxkl4333xz6hXExYsXHz3//PM3sPhRHNJiXIWlS5fu69+//7u6gQzZu1GKP6kZg7LwPgUMLUjSyuMvSwgZMsg7Yf6Du96XQUROOokfYL0OwOXjZDi+uHKnE3yeZ3P5OH7HF1fu6El6OT4Xp9XT8SfFafV0cqQvwWVLYui3lhBSZIRjuO24atCHu3QlMc+mzv72cF3o79FZPIIx9wmXlctjSJ2UbwnzYGxtjOha8JapHVVqxvDNAvkjGNlqLP/PA7SKk/JkyNrLZHlbxUKsoiEQQoBOYQkfQrSGyBVnfU9X6m0qlmYVDQFDwBAwBAwBQ8AQMAQMAUPAEDAEDAFDwBAwBAwBQ8AQMAQMAUPAEDAEDAFDwBAwBAwBQ8AQMAQMgVOOgL7Jy/odYTml9U2ernI8VmYInJYI1NLQBKAZ2mnZjE7KQ2f6ep+Gpy3if8k1hw+J9aX163yseT9fR79QiXbUzbN1YYy+2uZr/V7Eh5DThLz9lcgL10kyPO4T3uoTFlGSTzI85JXsYSup7GeSdArXSdIxSacIeYk6hut01zzY/ATd54NhTbZwcfzChMmTJ2/1v+rPBEsmQ0OyjOw7GNki4nUYymeJf3rbbbdNXbJkSeYvo30jG4ORNSPzMPEA4gkA9CbgZPoy2jVgxUmNE50TA3K8YaNi5J02jVPAaFMvuyce5P3OIFs8i8Ph6rAWL2EH72wNX7Pf8+STT0buuIC/gfKzkDcgeBaHw9VhLWHa2Yy8A9q9QXm1BjIPkdPZFHqdv19Nt6g4oNMITsZqZFPoRu1XyyIoa4/+CsIPAsAMdxNu2o+byhNlDjfeeOMFbBvvRN47rjK9RV0lPYarb3F1CPg75/8fUoaFJfGeyu3128M2lE+GjU1Ghhwde6DRUElAXrm9fupo34IntbHRcU9hVHQnBv0ljHUSsTvFSptCr0PW70oUSMjMmTOnL7upR7J1S7upG2iq3vOrM6DD2IS81GeGZDW0p7jhV3iIeVOnTl1ZrUHgiicBzJA+ffpsWbZs2R7kRu8wTABExa6XRcZ3OeNiYYoqZVlcL4uX3cFW9u1lmXtQIRskV9JAb+aRfoXhzAsbTvhRfcNcDP1qsF8F9jODPHrHeIKheLSPiLckGY4ME94J8A4i3sv5IpuC8uLS6H0dZU+ge98YHhmshpHSNTGg91Da5tnOuMIVtG+Ssq3I09kkiSHT0JFGt4Cbj+dhVrz11lsLebiHMbjHKjU4wNxG79Bw+PDhiWxvH8MxXs3Lly9vqcTgeOA8+uiEpvt46oV6cmd8SkcF1Ymii0bZ2sCWe8/QnPGVqxNXFqZXo1tYlvK10g38Zkhe0MjidBV+MkSMbR7nx2x1dVXfBWjeGTBBI4vTVZhztVO+hfrTXV0nKy72h7qr4HceLI41FZ3762i5WCNLJSTElGhoQZC5ebE6D3UOmUfYzv0IPEW6wC9mIhLwenMfV4QL9pL0Dn10+hXGohORXLHX4IuZMglnZHQGXyjDlrrIGdnAgQM3pK5kjKcEAYz4TwNGVqCj3o0iDdDcATqZho50MiPpOIrtGO/Vgcw62r93IsFJHzqGUcQgdPLVoyhyx9NPP13RQS1BmcjTyVfj+/btu5XTYJuDZUlp6haHnUnGniRL5cgrdgjqadPU6Qk8dFjdbujIu9Kp1merHdJh/2/el3cAr98mfsfUJNNiCPU0p2xobGzcOmnSpL1uxKY2gZEdpPPNvBiS6NGCjYfFi0/zIK/yIBrvKjzN9Sg9x0Avl/EPig/gOPBD7kFI78VDjsezZT7LpBbGFVT/dDKu4HMzL7qH3vzfQrtaw0HeUbHYYQyt2KnB48r3qK7LuFjTA9KDiOVdpofkRS6GwKvqx/y6SieFs/E4X6Gz/8cQo+Zj81lxLCoZKo/LNsiYwivpPN+uk768P3v27OHMpV7ggbb6vV4rWmrSrGX55+I0jqNjXDpz71yWS4+y/KqFkGOkh2mSSU+S6QQs3cO9fOQUF0McLU4H13CiyqnrebTgYoijRfGLlsY4k3QKyy6no3iTdIqQV9Y7+3OuT9LIT1jeD8vy82WX99Ffc663aKQnLO9HydOwjHeYdXn/eRZhwkam93F71D1S0PaHjUx1qvmvMqk9GosUu/Fol+HR/hog9PvEUK7Xub7Mcc7riTMFDK2D5dP19IhjOfhS5+1p+Vcuf4OO88okDGY1SDdPI7swa/0wP/JOWAwJ8/TUvL/SODPu+YR1XFkUHX55lNjVQ2EdVS8D7X9m4E1kZeqSadqSKLCnMcjQsnqMchhoQSSrxygnz8pOXwRSe7SuDpEMjKCDXL9bC11lYFpl1dCxFvJMhiFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoaAIWAI9EQEMn0c6gAIf0+Y9SNTJ8fF4e8Ja/CRqRNd/Kq/SPATleoc1tXJTatzGDtXPy5O0jNOnzLyUn3Am6SnPnXj49tF7OioQ8fE7fxJeupTtylTpjRv3749n/XgGz2r0zeMVxw9Dh9Hd/qG32sc3dWLizPv+5IgQDnbF6gzICoy1qBCo0eP/r2fbw8/WJDP0l0DgYCR/QMa/YbGpw27FQdnZGybmtza2jqZA59qciRBxQqdhIoVfVTMx7YzpAuAr1Fcbdi1a9dAyQBw7XGrKPDl/tIhQ4b8t/CJXJV2BHy5P5Ee9gO3KdUpVW1HUKk+7v7huFp9wvLC+Sh9/b2JMrKLuN5hB3PqdhSlr783cTKyGtmGdSSsQ0/IpwYo+LAY2Ax9Kc+1JkivNI0c7wAX5KY+vit8L2Tcunfv3kvpXa/nZb4VLs+apzMZzkbU/ojTsWLe1visMnoKvzwM2D7ApswH2cDZwXAxaGRfyHpmIu9KB+eeNWjQoKaxY8cW5MnAqpFNv0cGDx78TiVDx66OdUWGBlAz9GB4oDWKqw00as+jjRgxomKP5uugsx5ewTjuwDiWika6uO1eeRcoTxzycnBQX55xCo1iK5tbd6ku8ryd106Oi5GXau7j+F0cp58rT6On41Ucp5/jqURPjOz71L+b93Q1mMjjOE+W2cikBzvqz0TWSIaJgzAyvZ+aGVkSnrp/lpCEZ1pZmedoGlIhfALXFs47fJ+4qjB//vw+CGjgal+0aFFNhg14xkjjqlRRevGayqtUj1NVT56Me79BB3sBcYmRabNtVr3OO++8JuocVkdGXGJk2mybVV534M/s0eiJZujButL8LAC0hozXc35EceiY1SMEZOl46jYawyaOcSgOHSvxCEGZ4XQ1+oVlKV9r/SRT3pye/Uskf8PVgJf/ooaLlR4doWMsGI6+q4UP5mR5rg0aLsrIaF9juMd2ropCGM9qPVwYz0o9XGaPpvmZEKB3W6O42oCcqudn0gG9lg0dOvRSgCkaWTW60Zh2n3/++W8jr2hk1cjr7nXBoYXl/C+Cywx3cjPv7r5Kn0uGpTMzZWTI9k6p8o2sUpFdul5mjwa4M/REAL5GcbUBcGsyP8OLzYnSJa5H4+WWnaPFDYvjejTkpZqjxekTpbtoSXrG6VNGXio9Xf2gvhwD6JGhueLMcVBf5n5Vy8uswCmqkMmj+aBPkK4YyOZqdfZB1/ws19TU9Ilq5Vl9Q8AQMAQMAUPAEDAEDAFDwBAwBAwBQ8AQMAQMAUPAEDAEDAFDwBAwBAwBQ8AQMAQMAUPAEDAEDAFDwBAwBAwBQ8AQMAQMAUPAEMiOQNkv2IPi/A+KT/iaPI4erBuV9j8oPmH/VBw9SkYamtMvzJv0VXyY3+Wdfi7v4p729T7/9rjvwYMHH2D70Vf1jOzaeK5///736t8eR2C6jWMI5vHP2n/l8AjH7EGrW79+vXZWD1EZuz/2cSbLhzqTJYyp/o81+wB18NP+sJxyeV/Ov/o8/8a9k3VjPlUI1pu+47VU7f6WW27pz46FKarLFqH1K1asOKj022MuLtllf8GOVxN3RGT6el83sdDzEaDB1mNkv+ZJ/wQDm6hL6UOHDn0r5unPYl/Z4pgyGWmeIwvOw8hGwqPdGg1Kv/fee6Oi6mBkvTE2b5dIVHkZ2jzKdByGLqWrCug4gg6hU5fS1QjLvB+tmpt9HHXZudtv3759j7r9aZV6Lqer3xOPd/vTXC/pyrPG1eoTvl+1+oTl+fk5xFdwbaORfY2jHDa3t7dfhMf6e7/ci9yz+B7urGBZMD1z5szh5AfIU3FtbGxsbMeQG9ml/VGQzz2LPJOMLViWlKaONhDP5Frh894C7c+QWdGBT9Stp/MYhoHt9uUNh7YNecf8fKaoRxkaQExlM+EzIKBDeuZkQiKCGXmNnIQ1CbB1tsX7ESw9ksRwcTZeKMdw8G46mJf9hywxsvCDU2drmObyGI0MTbvgt7rhF9mjrjwqllFG0cvQZGQytsd8nm8Si7bYz2eNZGQa8XmHw5LW2ZXDXD6rsCyGpvHyYFm6s2ql/RtmGkv7ddQz1GtYQfDG0EpzDoWKM/ca6DKHen/L1Y+rGKCXjM9dAc9QdpzOyVcj0GccjaRkeI28S5yMYIy8xHG6+OP0CcoKppP0jNMnKCOYTqmnOqocPfqLwbrhdOBZtvEObw+XuzwG2xdZucmTJ2tIFxvcs8jIwH1LLGN0gYaKv+X51qkYWb8lEm1x2jmZ6rmAziPQ+QDyvKMskHdANMpb0szJnBwXZzG096h0CcMIjZ03SQA3nigACSrLFKh7hLr97rrrrgYqeqdf+WnJzXwaloyVkEmHcsw6+YrhUjkWK+siCPgG6nWApEsagcpSdi7Fp/EXQbwO25ftlamtqyzglYt1khKpDY3G/zA3eoKe5kFufqcE07D/RrHKFGcJnG7bzEGcE5ubm89iXvWB6iqtWGWKswTmZMvQ6xXquKGjVx2Qy3quuHtw8tVu5B2id53EM2vo6IWsL83Vc3Gl+rj64bhafcLy/LwOOPoc7/VKYuEZGdyzgFOBtqEh2rgoRsp02MiADRs2DCQ+flBIBKN7FuRdAu7q0N+IYIsiyXMdpD3+d3T2RkPcs57O927oKov1tlHCGCZ6iyCU7QyVj1IZNG/1MVRWNpva0JgIP8mwTuNmrTy96UvdwMPcSNnqsneJKPQbcgFgRjKvmiYWwG0DoM2U7YmokkjiRb2F0V6qxZBE5hQMyDvMYsjbLEuPT8HeY1hosMt5mM8R/5Aj4D6IWwwJPXDsYgjvdTed1QDkjcMjtLvFkCeffLJkMSQoD/5UiyEYpVsEWfSzn/3sO0EZlEnGncSpF0XgdYsgzbz/7SF56rRHwpN5USS1oemGeA0ZVGajUt2owIPIoCoyqih5onGM2SGiOUorAErJUOI4Nfl0Kcen33lIv+/yyDsd5mhLed45GMYV9OD/zOU9Ph3tX9AE7g9gUcSWDjd2MWTlypW7qTtcxsY1xZ2mxYnF24PHiQexxTjTLobM5N796LB/4vRyMSumP6HjvofnyLIo4i2C8I9Xdjk5LhaNQ6RGk8+8KJLK0OIaq1PAxRhOqmFaEFBXNypGXqoFhqi6RqscAXA/xg/WV4V/sO7Xr1/cFKHsYgiGUKDDejf8g/W5554bHpp5SsvIMMi0iyHzMKRfuZ9fgk8tGm1NP6Jr+Jhq9RGD1SLI/qhTs0VD3n7xIK8leC9LGwKGgCFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAgkI8K3aQl0JbKmL9f+Ke+o/Bk8NgjGeNgik+tZRaPA92X0+Kgv9uKqID1XH+AJKvpCuSqhVNgS6KAJlPwJO+pg47UfE7tmTPiY+HT4iTsLUYeXiJIyTMHVyXFwtxoxqltLpzkDORCezmphRzUQ63YHI83ZGVyOrK9ct69H46vq7YeUBeR70VuirwmVJebYt7AjzIEtfS3cS13S7TPg+ls+OgJsqsDVmoastI+NdrVE+qtzxRcVuqsBX9cVRjIyMdqH2lIsqj5LTHWkl52GEHyAA8LmjRo26X3lAVp1/CJSFq8XmHcCA24cz/ZqUl41xfeTKYiv3sAJ5Kne5R3N5xY6WNqbOWne5Oi6v2NHSxjIiTRe4rtXJYqon70M0Adoa0VTGdZ8zOPHEBRmRpgtcQ3SymPjmz5/fh6iBNnVANJWJxxlcnKzuSC9raP4DHQHMmTt37lzDMOWPSY8CmNdURv7nGgoB9P9J+/DsNdJmwWGcLjWZuoMxMki9tFlT8s7luuTGG288J60846s9As7IkPwG7+ZKfzNtDiOYobvhgdaIpjLxJBmbMzJ4D0+bNm2Dv5k2t2vXLh1tkBsxYkSraCoTT080tlQ9J43/WoxrBYCqZ9P2c21bb4T2IbTdxMOJz6TnTLUZjnP+hmJgGpvL0LV9d93QoUPr9u/fP93P1w8ePHgdLzPtLlsZaXG3LzISA7qWfXYZfKKQAENar9HV9Qwb2apVq4o7jSk7YX6m08LYpPkiUFxIO/hueKQTYWQdDjbKTpifYXC9OGx1MjyNmmqkGemg1/OSyb2vUZyUF0+5QPs8T+XsDH9XcVJePEkhjUfT4TvrMaRXEKbGqXMYroI2C5rmeDf5sbaLpwpHjx5tw8g8LwaYec6kGNTa2jpMw0iOnd6kWPlUwozpY0OA91ycn9XiprSB4vysWnnoVtLRJuWT7kcbLZGXlE+SV7ZXV2V64N8TTePSEXCao32Vh7ic9F7Sr9KLXEUP8mtoI+jVPwW9bKAHnEYP2BdD1clJ2xl+DCHfn0rHoB3ioJ8NDB0nU9YLeW+VFdYNC51HC3rUtLSox6Wu53mDHjUtLUqeaLxPb35G0hs6yqv53mcztLncaylxLsmbiUchyqtpfsb5G5/g/W9xXrMSb3b8Dl3/bxqP9g6P8W0O+R8PwA+wKDKD/LNcwzCuL6mRKCZ/EQbySeKyAQPS0WMfamiIvKbzzz9/Awa2D5pOHxqoRqKYfKObhJcVaIU1R0DDPw0DEXyhhoV6D3ifGbqR5meKRSs3ZBSPCxr+aRhIvlHDQgyqLjg/E59oWYeMTn53iBM9WtRDYAz/gxcxm7IfBcrvwuCWYzx/GqClStLjjeNFDudlNLsK5EeS381Lij1dyfF2p1gdUxZ9wbPsO1LHlFHe2rT88mzileGRPmF+FixPI1OeTXwyPN9Dlvx+FixPI6878ZT9HS3qQejJenMO40yM6kkawULHwwsfTnom5QuyLGIgJw/Amo/tCU58kdeLMnlNnbCUqXE6nSyuDgEZmJPAezhhfhYsd3zl4uD7pSM9YX4WLC8npzuWZTY0DifVys4ZeJslwQdWHvDu9Mt/Hiwrl547d663xM+qY3F1S/zKY9BnqJyshpY9IiR5qKwPibzUHiqr7CA/95kYzFebRt66amVYfUPAEDAEDAFDwBAwBAwBQ8AQMAQMAUPAEDAEDAFDwBAwBAwBQ8AQMAQMAUPAEDAEDAFDwBAwBAwBQ+DUI1D2g9VTr156DTZu3Jjpe8hzzjmn7LNv2bIl08e6EyZM+Fg+hUqPiHF2JQTSbJPpSvqaLoZAt0Qg9UfFbIm4gS+49V/vV/FB6Pfd08bRXXlczNf5w9j0N4aPkfeE/mF4JD1OThx9+/btuR/96Pgunrvuuis3dqy3QyOOPZH+wQcflMgbP358Yh1jMAQcAqk8GkZxFUb2FJVeHThwYHEPWhzdCY+LZ82aNYiys9k4eOjIkSPFPWhx9Dg55ehr167NNTQ0eJfS1YZXX301xz9L9y6lax3Y+KjzWGoWtJGyZsK6maBht2wvBK9K1A/WD6aH37Lj3RG3bs80rdD9076Mu+DNsxP6e0uWLGkNKB5HD7CcmGxvbx8pKueD7MA76nAeL8TRXXnamO06uddffz134YUXepfSolUaOC8it27dutz06dO9S2nRahW+/e1vf76tre19xbWQec899ww8fPjwdMW1kHfvvfcuCOsGbYbolchfsGDB6LBuyoteibxwnYb6/NnHafkte1aMLTsXD9dNyhdyhXPZQvloEl+4PK2heQ3gggsu2BQSEEcPsZVmGS56DeDxxx/XOSTFEEcvMqRMrF+/Pnfw4MHcpZde6l1Ki1ZpUF1O6MpdfPHF3qV0NfKCeqgBM1p4BtpDisMNOsibJq0Gy0bZSRwHsVNxuEGnkRHmQc6/BHXzdVwtepg3TZ56B4O6OZ1FT1M/iYcucIZ48vncGsXVhmFDxvStq6+7uSin4J2hU8ymSaQ1NM8wONPhKMPF4OpeHL3svfEu3n2Z312MvKIbjqOXFRZR6IaKjz32WE6XgqNFsCeS3FAxKM/REiuXYXBGRgO7/oEHHnhIcbBBl6kaWeQaLDI2PfTQQ02Kgw06slIK4v333/8SbJqjPyMvpli6+vQUEkpZHnzwwVanm7yYdFRe9FLOCnOdxw2N8dqaCiWUrVbI594oyxBRmNbQIqp2TdKBAwdyHM6au/rqq3M0Xu9SWjSVZQ3Oe11zzTW5H/zgB96ltPNyWeUF+WlclwUbbKBBXxbkS5tGXv9gg3UNWvS0MuL4wHKNdKV8QVDnOP4kutON6ciooM5J9dKUc/DcDPFxLuIaxdWGPft2tHUe61zl5DAWXenSaeMeZ2iaj/HivCGeA0FDPtFUljVoPqYgGS64tCtz9KyxvFjYK6hBi55VlvjlxcJeQXnRK5EXriNdOQ1tYljnMF/avHRrbGxcF9Y5bf0ovtFzdkzkfx9NYOC4pWnpmPejeKql0ZYWDb+16XtZ5PQ4Q9MQkSPscqyOFnFQWrRKho8vv/xyjv8TkON4vKI8pUVT2ekWWM08VMtnRl5nLeXVen4m3bwFlT59xnF88G+droVC5zddOk1c0xWZNDc8WTz2ZcjJQrZ7yR0+e4eOxbs1X5+fu3vpmKWVaq8lfVdXhjZ27u5xbceOrMwVcleIzvC5affyMWMcT1Kc+gfrJEFWbgh0BQRqPT/TM8no2jpKFsixt8IvszxvjzG0pG8Xs4AiXvt2MStip57/uBc67ojajxU2o1HNR2z8ZHCkkMs/lxvc8Oen/olNA0PAEDAEDAFDwBAwBAwBQ8AQMAQMAUPAEDAEDAFDwBAwBAwBQ8AQOIkI1Px3hpOoq4k2BGIRCO0qKfKx37HiNh7cWVIUSAKZa4P5NOmKlUgj3HgMgZOJQJxxxd0zjdHFGVcZmamMrsd8GRIHhNFrhwD/o/wcNpS+IIlsb/njp59+emOl0vXP4pubm89T/ZEjR767aNGi0m+cKhXcReulNjT3kWV4a3gcPc3zXr+6UP/iL5v+Et45uNbhbKh7vb6ucH/L0rHey0wjw/FMnFPo29q54wE+j/mqaPlc4bmBdWPufX9pvs3p6Hi517a6fH5ey/Ixv3K0uPhk9Jpx9wrST1bPGrxHUhodPg/Ps1zX4Q1e4mPd/0j6XNXz0z8M86gsKtx2220DW1tbz2EnxUYdh8E/ix+C0fYRr9JEO8M8UXKiaPJUce+pXFmULEej3tq4d1CuzNUPx6kNLVyxFnnfyL5TV1dY1FmoW5cvFD7beSz30xG3tUzdteSM1LttPYP9ux2/Pv5l9fFv3fj7J62FnTvR8/6wrpSd1VkoLIY+Llxm+T8gQIN6icZ2HZRnFfPF+s8xsG+IQ2loJYb4h5onpmRcGNJGGZtizovZh0c7Q5wjRozYV6mRuTvJoFy6VrEMqlayTqmh8YHmf+BBfrtr2dhv+Q+0ZOy8Qr/ti/OZ9jy9+PzOOTIyeapcr7qv9eqT23z0cP6i3ctG/X0QKOeN5eFkbMGyuHS1L3DmzJkTVq5cuSUsP47u+Kp9yRqaRQ3H4ujuvuEYPYrGhgeSZ/OGe1mMzMkMGhu0jQw9f6+yao3Mye/K8Snd+Elj38gY5LLhs7d/feHCgqdLViPzwC0UZitm2Hj37sdHv7zzx6Ob94SM7ISXkM9tPYFWY8JNN900kdOyXvEbZVE69Bmiy9iKxBom/PnPFDXgoFjl8SJTVB6kx6U1J+Nclz9jPrYNHufZPh80MpWJR7xxckTXPW+++eZReLJ2DR99zzYwaGQqE09a/crdr6uVpfdo+fx+jGKwhmnP3JD3zm47PsfaoXHE/koerG99w4K2Y+3jkbti0aamhcNv3fHw/LNHP7ZwYT7brttCYaru36+h34t7yiji5mreHC2Xv70Ma7GIRkV/EB/KebynnnrqferrnI1nFPve4fMcQrQa2vVRns7dCfZLXDoqRlbssEaejAa8idO/Jin2PclA5WnMm6I8XdQ9/IUPjlcrfEOeDJ1kbM/5vF/1n+dd8h4Pseft/PKSSAsfmpNpuChPhl6esYnJzdsw1k84HsietysR0o0zqT0aiwvv6Tn/8YXmYi/80vPNE0VzZUonBTV2d7GZ7gOM7DOqw8s8p9BZeORHG3ccc+XOMJJkduVyNUaO0bsBHWVsCxRzeUZ3MvWWccmoZFzcd7QzMtFP5n1NdjQCqT1aPl//cKFw7ImOo50PnjGn+U6Jo2f+G8UqU5wmuHlSFC8e7ZsY26NMtO9gm/ijUTyRtHz+LSz1c4faD11JuRpyZHD3lgGnXQzBUKqeZOPZ1tDYPc+GYqmMjPvGeqzIh4sg+p7MMzYZXVYj0xK+VhdDCx/eqi638xZIgjwRKhRJWsLX6mJ44UMMgQWSIk+xYg9JpPZou5aNerK+Ln8j7uvMY50db+pSWjSVVYLHsDlNn562sNDg6jb26ve0ny6ZW7jy2DifX+6V5Qs/HD636fJR32gaOezWnV+O5aeA8WCqxZByMrKUybMNHTp0ouIs9arllXFx8O26rEam++p3stWrV/+Q4ZywepbLW+b3n8Gbs6lMPEm/qWm4umrVqp141obgMr/0cnM2lYkn7dBWOnaXkNqj6YFalo3R3EJX1eHM2R8NP9x58IUdG5u2cnQXh54UWg+1H7wZ93E4V9fbzQNS3efKa0YtffHvdngrj4WOzn8+2nG8GnL/Yvey0cXl/ZKhaMrFEBxR2TlaWEEaYawHXLx4cerVVO5bdo4Wcd9YD1jNSVPo8Xnu5RmZFj7Ia07m/WCNkXnGBs0zwLBO4TzzsuJvaVr40JxMPKQl0y2QeL+zhet293wqQytpoGWe2A3NyrAUiz5cPmj3iNktl3XmO/6a4ck8CoYyRHm9Llf/5ZalIzKd363FGX6wvuqEH6zzox7eXbzjHxJYwra6lIshf6h1+qWCRiYvptVFUDhXSGhICU0/WKcytqCRyYtpdVELH5KlIaU8mVsgUZzFA6NDps5Q90wKyMzU0SXJi+19kypa+emHgJbwMY4u8wlWVgMrN9pwbzOrgSEzdiThZFpsCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoZA7RGw5f3aY2oSP2YE9LX/zp075/Pb3n/i1udz6WujN/ld9g2uH/PVyqtZVeJH/jr+w+3IXr16Deno6OjL96qIyh/WNWDAgJYsHx/o3mZoWd+A8XcpBPjd6woU+l9cMrBjGMIGDG4H8XnEZxHrx+zHSC/gN6/DpBMDMgfwFcxE94M6xtZG+ii0vhhdb19Ay7Rp07al/eom1ZchiZoZgyFwChBgX99nMYA1GFEbBrWgX79+jyxdurTNqcLXJ1MwDP331Dso11co/9WVxcX+FyyT4ddWrQ8xpuagMc2ZM6cv32Tq288zNmzYIEe1JU5WkG4eLYiGpbsNAjII/ie5/mn7GRjFpQwP3+bLlU9jeH+E59nJ95O/oPxqyvVvhb+FMWoXwtf4AFrfbUYGPFk9BVMZJvZiZ8p6eUB5Nzxa/969e3ccPnx4H+WD+Qj6KMY2knsNgb6JfYV7IwUGiObRAmBYsvsggBHdg/FMROPbMbL1pJfQ8OfqCYi19WYdyekY10/4v9v/pa2t7Svk7+KKNTTKRnM1YGQfYJBteMSJpIfjFXO6CBp6NiJrFzsitjCHG8JO+ZHQEg0t9TYZ3cWCIdBVEMCwZDjtXEv52Pkb5OdiVBvxZrdB+z6Xt+ueeMvy5ct3U/426Yu4yoXB1C8wXNyNzBEyMvJH8GgaHsozNqoytHaGkx2au+H9+omWFMzQkhCy8q6KwCQUW8fwTsZ2rZTEAGbh3R6H9lcY3RLRMDA3h9pFuuwRGRiN5nGHNSdD1lDVb2ho2MzOgl3I/JBh4i7RjhAU4+U6MMZUOwfM0ISYhe6KgGu//fUAGFJwCOelMbgtzLO03K+9b4kHvjLs9NYtMDRPNsbnnY8j+chyaXk0lTfClurgV5ujCUEL3RGBTTT8T+g3tKampt/wAH+Eof0Yo7obuk7kcudPtkC/m/xwrh9wxQa80xEMp6+MiPlXK4z9WQAZP2/evG3MCftQ7p1DyUJLh35jo7wewwwad6xsM7RYaKygKyOAMf0CA7oQI7uBxY77WaC4lvwX0Pk1Yqnu/cEQXiKtRY434VukgjJhP/yNmzZt0rCxiTmYfqweuHfv3guCdTA+/WZHca82yluCZXFpLWdaMAS6HQKXX375v7a3t89CcZ2gvAoDeZhYwzsZmDzcDVwaUnL6e34VS/K3Llu27AD52MAiiI6aGIahDuU3uT1MxZodM0PIVmibuY+8mOZue1lxfJ+5mxtOOtbI2BuPRpYY0RDo4ggwTLwKFf8v10dc32dItyj4g7XU93/Uvpzl+rLDRvEqzJo1axAGfB5JGVBT+Adr8fg/avfHyLQSmSqYoaWCyZi6KgIsw38OD6RPsGQc+rHrPa7NXFoA0RDvLC790KwTyPYTJwYZEj9IT8BzaRVSY0R9edLOHC2vORzDxd6QZYha9Uzl0WzoKCQtdFsEWJTYctlll/2UYZy8Wn8MYjzxFC6tP2wk/yjx7LRGBm/utddea8db7mppadHPAVpdbMCY+2J4ckxHSGuZf3NaI4PXgiFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhkAqB/w/mpdIDtoo4VgAAAABJRU5ErkJggg==); + background-size: 218px 188px; + display: inline-block; +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2), + only screen and (min--moz-device-pixel-ratio: 2), + only screen and (-o-min-device-pixel-ratio: 2/1), + only screen and (min-device-pixel-ratio: 2), + only screen and (min-resolution: 192dpi), + only screen and (min-resolution: 2dppx) { + .tui-toolbar-icons { + background: url(data:image/png;base64,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Xqz8qBcJkED0BGIbcoxe1QtDor4qT80zFpNh01flYWg2e1Fo2C6Me5NnSQLFToAeWpFfITFmxbrCUdCJMeMKxyK/iageCZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACZAACQQgkA5QNlTRRYsWZbwEbNu2LTFdnPSAftc6pas06PesihdTmIurXdekOefi6qBfpJyD8rHrk+s4LM+gfHLpY8+P+r6Ngmc6nf7q1q1b6+26RnEcBc/S0tLmLVu2HI5Cn6Ay7Hxz3V9BywfVx17ezjfX/RW0vL29oMclQSuwPAmQAAnkS0A3ZrW1tR9Gh1ebr6w46unGrK6ubiz0GxdHO5QZD4HEDJo8aeBmmWk7jf2SnuspxFYnlkN50pg8efJLNuHdki67LZ2HJEACAQnYjVl/f/+PIeLxYjFqdmPW0dExC/rNpFELeKELWDwxgybn2NfXt1A/V9zg2/XjQsePHz8+StcBN/gZ/ZhxEiCB/Ai4GLMKSCvFXnCj5mTMYHDVNAiNWn6XPfFaZUm2iJt6YSZzfioN8e1Jtp+rLegzUi8Dfdv14yTiixcvbhw7duxdDQ0Nb/ppL2nvdsmSJZfMmzfvQH19fb9P/Qrq3SbNxw8Tvcxg9/6D8pVhRsMzE2OmthJslodJlRE2DMpXhhnFM9OMWVaFsrKyRB/+w573hVo/0YsEg7FQB42nou36caHj8CAtP6qamprEPTQwuq21tfX3GOa4vNA8nNoHo/G7d++eD/2qnPKZRgJuBFyMWQbGbHVTU9NDbvWSSvcwZvs3b958PCk92E7+BBIzaPJkDzVnaKrux0qi17XjgkbXrFkzDAroT43da9eu7SqQUmLMxKjVFah9z2Z7e3sr8TAyb+nSpTWeBZl5wRGQewKjDP/bfuLFYswwslAmhsuuH42ZncjgPE7MoHH+LPANMhw1HpUhyNWrV0u8qDZczxIYthnyoIJOIrH7qKggUBkLATFmuCf+E4k/xsPYCpVZTMZsx44dc86ePXvpypUrxyv9aMwUicEfJjaHxvmz/G4WYwjyOnQQizAf8LJdCpLPT0raMx2Og855OIiwJBlDkCOgx17I7rBk4gDpnu/32csHnfOw1w96HJSfXX7UPO3yg/Kz10+Kp2bMrsQ9m8LvvRG6pzCc2OowZ5b4MKN4ZmLMwCc7VI55sktg1ES/Ppc5s6IYZgx7f9rvh6iPw96fUeuT2JM1589CXToOQYbCx8pxE8CDzbUwYvNVO/i9l4hRKwZjJjrBmI2A8apU+kkoRq2YjZmuK+P+CCRi0Dh/5u9i5CqFDiKQN5ZLXtT55eXlRa1f1OdLeecJ4Msfv4ARq8U92qNSxaghrs9LO3pmGFavV3XiCuGpnsK87z4YNcs96rCacYBnhv5ralx6UW60BBIxaJw/C33RZKjxOnQaj4WWFIMALGnuxDXetX79+hMxiKfIQUIARuMJu1HTVHc1Zqhzr1YutuimTZtanYyaahD3saMxw709RZVhWNwEEplDw1Mb3z/L8z4Au8e83kuLew4nl9roIE7MnTvX9b20pOZwcunpll9ofm56qfRi56f0VCH0fQLzKrIg5HHs8tJ0doNn9En70nzxzJIyZkoPMWrQT16Ytny1qLKy8uCGDRssS/PFMyu0Mct1fxZ6ji3X/Zn0HFsiBg037UJ1Q0mITnC7flzoOG7agr9/5sDgTRizu4rVK8M17K+oqDhAr8zhyl3gSejkmtCRCYWsUYMx+wSM2TodSyGMmWof+p009MsaNcOYHVX5EhaDMdP1YdwfgdiHHDl/5u9C2EpxiNEGhIeDi4AYNWi83MmYyZkk7ZnZ6YlRQ9o+J2MmZQvtmdn15bE/ArF7aLgxFuqqwOvYrh8XOl5s32/MNcRYaF65hhgLrR/bLx4ChlErHoVsmhhGzZbKw8FMIHaDhg6a82cB7hAMMdYFKC7veVlWbeWqix+xzB/kvQX9ukvQMXTo92zeyjlUDMrHQYRnUlieQfl4KuOQGTVPexNx87W3F/Q4br5B9WH5eAnEPuTI+bN4LyClkwAJkAAJnCMQm4fm9uSGIch9yEuFfbINewHdntxaWlquMPSL1FMIqy/rkwAJkAAJeBOI3UPzbp65JEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJFC8BNJRq7Zo0aKMLnPbtm2ebQQtr8vOJ472rtXrQb9n9WN7PGh5e/24j+38crWX63rkqh80384vV/1c1yNXfXt+UD72+rmOw/IMyieXPvb8qHkq+dB7TDqdvgPHtZlMZrak4/gVBE04fgjtnpI0tfm4Ds2ov728vPwLjz/++CFVL98Q7ZWWlZXV9Pf3j8M+TOSUlJR0YT/Z29t7HPr16bJzXQfI6oF+7T09PYdQt1uvG1fc0Om/bfLf5nRNX5xytaXftdVJvaX5j579sL28n+MVK1aM6OzsnKeXrays3LVhw4azeprEd065xtLv2vPnN//Bsx+2l3c7LnHLYDoJkAAJOBFYvHjxDUh/CYbrO9ivQ3ys7BKXNMkzyiDqe5uCuku7u7ufX758+TTftRwKrlq1ahQM0AIYrmkwZsNRpFR2iUua5EkZh6quSahXDmNWjQKXw9BUuBaMMAMG9E67OKc0e5mkjvv6+mrsbTml2cvEeUyDFiddyiaBIUYAnfn7YXh+jtPyMjrTpMySJUv+Zx6nPw6G4+/yqJetAmM4+uzZs7PFALnJkDwpI2Xdynikl8KL9Dp3j6r+s8B5pBh4ew1Jkzx7etLH0EEeEMbZ25U0ybOnJ3VMg5YUabZDAoOcwK233joFHkITTiM7hOd1Oij3Mzytv+BVxiPvfR55rlmrV68uh4c3C51qzuG10tLSthEjRnS4CvPIgFFJwqAsgwrZdsDy97IbKkma5BV6G4frm7UfGMZ9U3ZRyEgbYOiSUrYsqYbYTjgC+LEOb2trW7d169Y6XRLG03P+ePXyccXr6+tLdu3aNX3Lli2v6204jffr+XHHi4WP23kWmo+bXk7pMBb3ozOXYTd9a0Rn9nUM4x1D/v9Ax3sP9n9oamrapheyx+3XBU/15hwQ2phqL+/nuL29/WKUs3gHMFwnJkyY0NzS0tKLvJHQU4zykU2bNrV6ybRfF+hnzgF5eX9eMoPkQcc7wSFbBfHvSwTHMrwrc5UyFNkg8UJtuOYyP5ltHvFjEsHxDAklD0E2TY6T3GjQkqSdZ1v4MV3e2toqHcTl2OvyFBNbNehXtXv37ll4OqtEI6/H1hAFF4zAsmXLZmAocJGuADrW7+IB624t7V8Qlz3xbc2aNcNgtCzGtqKi4ohtgYksVJG9qDcxnjBe14iSYNwKQ7HFiH8X6dWSJ2XsRjepkzIWg8jcpGx9c+fOPSmRHTt2yFBsdq5SyjgtDpFycW4ccoyTbgSycePWQczvsYsxK7pt6dKlNXgKnoenVjFm3IYoAVzfJTg13fs5MHbs2HviOF104oeDyrUbM9Tv3rhx4xtB5fgpDy+vx0+5EGVWa3UbYbg6ZEdao5aul9GS44/iwdVcDCIeMEZn+mWXuGpdL6PSkghp0JKgnEcbMsSIlWKNqPoodvU0lIekeKrIECMm/S9BRzfDGDePpyFKLQoC8AoW2hS5v6GhIZaOHW1tt7WV8xALNSyrFmF0jsIwmsOYOQUEKIB7/kyA4oGK4gFWnyPL4Bz+SQkw4uqclhllVXYiIdq0LAbBMn1zaFGPw6ssyOKQOIYcxaUfkyfdJIYD5P0T/UkziKqWd1eCVAxSFjeNPsToWRVl1Q3uWU5l4kkv9Jwb2tSHGJVoxxBlzbkHxwK2xKiHUYLysamT8zAsz6B8cipkKxAhT8sIAZ7G/8vWVKBDj+siT/lfCCQMhTEcahkhgEFrDypDL+9xXaQPiMXzM9rXF4P8J+Yi9yi9JI6H3P+Ewb8JacrwZefS4njPTLVrC/XFIGcaGxs7Vb7Ea2trz8CYjTIecmVxSNbgRfWemWrLLYzDQ9uvN4YbI7tSR09TcYc8S11VLuKwW5cHHVyNm0Oepa4uJ6o42qyDLA4xRgWUcqIiYA4ziUB0WPISdZSbvFi9GfNeV8EIBzYYMLCWh/NLL720K0rlZJgRXqAsJHkZ+sXZD5hDieCRXQyin4ctzSyrl4kzbiz4yDYB5qZ3ptrU0/SyKj/u0HITRNEYgO/HE8SVShZOairie9SxHkoerLmZJHXNg/gicjNWKfFYuluOuKPnJXl4X0UVlTDOGznbDhgAXyCnS9cv9jh+1BmsZou9HTZAAhcaATzMymiGOaKBvvHHSLNg0PtLKSt1IvTCLW3ZD2yLQcQrnmXXD2lmNeg6POnFIXF4aC+aZ4QIOuf36cd63CHPUlcvG2Hc8u4JDJZl7F1vxyHPUlcvG1Ucq8Yeg6zrsL8clcwo5axfv/4Ens534YnVHGqIUj5lFS2B47pmeBKfrR9HEA/1pRDck7Is39xee+21nO/KmYV9RDBvlsSXQvLxuPKp4+OMBxYBY4uXPrDEwJR86gyU4j8lcg8NHV0jrPQXoUJ2KA9G69Ow0pvsSzgNa/9pTdU+lH1UO44lCq/rBAzVZCUc+k7EU8ZJPOVYvDSkybfgJuJGVkVTUtc8iDECXV7GopDr5L0zMLnNqymUTXvlx5GHNjuwKGSnvHeGG3a8Vxso+6xXftx5heAT5JwKzSeArvKANV2Vx3V/B+LPqOOgof264PemhiXUl0KWBZGJkYNO9DsVqg5+tzLVYRleUXl+Qvt1gX7Kc1JfCtnrR47fMpCv5sT8VlHlZHHI56BvqDlDJcwtRBuWxSBu5ezp8NJkcYh8/9LSv9rLRXUcuUHDC4uvYOLyb9ERf8VQ8vKurq7fYLLwHpzcHyUNQ41XI+2biJoTzRhq+1t4J68adWILZOISq/Oa8YOcIo3gxpfJ5LmA/kZ1dfWbkoZ3vmRV4UVGniSl8ETarE+AZhNj/IMVZKJLHVg+DZbrEC+qlY6yTBc6vb5y5cozGIIUwxaHtx8jYYoOQgC/z+24Dz+o1fksHrrWxbTS0XVUR2vfEoUxO4ME81NW+O1OhL6xrHSEXNd1ARalgh2IAc/KBesfoy/8mFd19As/gh4fNepI3Qav8hHk6YtB2rBA5TUvmejvL0V/P9boF8zFIV51osiLpRPCyd6Li/JVKJh1bwD+rTi5f8Vxs+wSlzTjBHqlrNQxjmMPNm/e3CwGSmtI5tQugyG7UnaJYzfn2aSs1NHKJxblEGRiqNmQBwGMVmxBtv6UPR0jCPJQGvmGvmFqUKGTJ0+WBRv6VoFPdV2kJ0QVh7GUefeoN3PoEA/8AxaD2BuzlTHr2stFdYz2zOFG3AsDFoPY29HL6HXt5aI+jsWgwUBl0BHXyzg74l+H0v8Xu6xi6pTdiP9K8qSMlEVcDTlEfY4D5Elb+ETTYfwIXkJmC/Z2XIAegM/ILnFJkzwpI2WT1A/tWja46y/De7wOOsj8WtFt0K8DXwvYiWuZyJBs0QG4ABTCyMt+3H/b9FOF4fkcRjYeladx+dAvvIZbsP8ax9aVDHqlmOJr167tMlYhmi1g5GCSvCspXxGRITPsY/AhgHn46km1WagIItBLhjOzQ5pgvAcPz0/lUkvKSFmjXHZxSK46+ebL9BCckOwIEfrHLrywLt6w5yZlpKwUkroiw7NCRJmRDznqehnf9VNDj3pWUcTlRwBFAi8RLoTyagjS3jZ+DIEeBGB8YplzU0OQDvplf6j2dLdj6BfpnFtQPm56uaWH5Wl0Zm7iQ6dHyRNL6j8LI/EnMGS6QahDh1Wnr3xF/rth2LYh/ATad3ya97ou6KgP53PiI0eOPIgRFhl2NF/FwZDXeHxFZLySB+9KorNg1FqlvNuQqdd1MR54lcgoQtPDwrl/H3vO37SUwYPD98H4e4YCIuPOKJSxywBD0zuDkTrmVz88PBzDvTFN5Bky8p7TtOvkdhyLh+bWGNNJgAQGLwE8dTejA63FGeR8xwvl/hQeu/n6TpCzRt3tQcqrsmKcYHT3yiiLSnML0cGOxeIwc1rBrZxTOoxiTg/FqZ5TGgynvhikA8x8j8IYZdXK61i+HAL9zMUgwhUjMb5HYaSsuhYwbIl8OSQyD83ricvpQuZKC/vka5fv9cRlL+vnOMonXz/tsQwJFAMB3PdPwvu6GUZnPfTJPn076HUIT/ErMULztENeriTpML+Qq5BbPj5GfBr/vPOVjo6OmW5zXeJhVVVV7XvkkUfyMUwyjxjlqI4s6FCLQbbk+i8A+nlLWVyLLbgWtxsyRFaDXiaCuLkYBNf0JEZisi6uH7lSFkO+J1F2PB4gxHmKfXEIPTQ/V4ZlSIAETAKY8xZDdQU6uLux/x7xNtkljv3zkmeUQdT3FupLIXorYqhgzHbAcB2ChyCrhcUI9RnxNyQvqDETIxjTl0LM4UboJ6uZA222OqasQEI8CkO+OdyI83ccPvaontLr6LK86jCPBEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABCIhkI5EiiZk0aJFGe0wtW3btsjb0OUHjUO/a/U60O9Z/ZhxEiABEiCBwUmgZHCqTa1JgARIgARIwEqABs3Kg0ckQAIkQAKDlEDew4H2ocWg5x/3UKR9aDEP/TgUGRRaEZYPe5/mOqWw93HY+9SHfgW9j5csWXJJX1/fPkPP/eB1SS6dk8xfs2bNsJaWliuMNruh34tJts+2oiVADy1anpRGAiSgEYAxW6gO0+n0dhUvlvD48eOjlC6lpaVnVJzh4CRAgzY4rxu1JoGCE1i8eHG97F6KwIgtVPmZTGa7ikvop75ePmgc3uFU2b3qQaeRKh+6tqu4hH7q6+UZLzyBsnxV0IdaMGxSumDBgkx9fX2/XR7yfoC01Ub6najXYC8TxzHaMYdacNNmh1Zxw1pWYEq7y5Ytm9HT01Nj6HAA9Y7FoQ9lksBQIiDGCL+re+WcEE9t3bq13un8UGahSocHtF3F/dZX5YOGYozgHU6ReointmzZcthJBsqYHlpNTY3pofmt7ySTaYUjkLdB01WGoXhgx44d02C8lsMgWJ5ykDcbN7UqvltFkgzx47kY7VVAv33Qr09vGzf0MHU8atSoThVnODQJ4Po7zhvj3jBvUjlzv+WipoR2zQcxXTb08/W6ib2cLiOquG6MDJlfXrp06ZbNmzfv0tuAUZD5sxlG2n4YldcljrLzkP5lIz0lhtHLKKpyfkPdGEkdyJ9cV1d3srGx0fL7NubPKgy53WvXru2SOMpWdnR0TDbSU9B1ipdRVOUYFp5A6CHH2trau3DD3IVT+VPsvxGPRz8t5M1Rx2VlZZYbXqXHGa5YsWIi5E/APgb7XLmJ9fZKSkoq1TH0s9zwKp0hCZDAOQJ2Y4YH1h78xmvtxkxKwxAsPFcrlUK57SouZaWO1FVpOBajVq+O8w3txgy/7ww8w312Yyby3ebPpKzUkbpKD8OoeQ5fqrIMC0cgtIeGG/EiTf0rMXz3/+Gm+giexn6Lp8WrkKfy23AjH1Fljbw/qmMJcQNd1dTU9LyeFjbe2dlZrsmoOnr06Dy0/RqehNtXr149vLW1VeX3NTQ0mD8wI2++VjdVXV29E2Xe1NMYJ4ELhYCbMcNv6QknBjBYC9E/ZLMQbtfLSB38DsWoNSEv+xtEGMpTczNmmzZtatXbVnG05zp/JnXwcC5FZ/b392e9enpqilzxhqE9NIyd/xUM0W04xay7jnAiLvxT8NxWIv5xdeq4cX+q4kZYZztO4ca53Z4W9hg/nDeqqqpeV09baKMM8TkrV64cD2Om5s5SeCJr09s6ffr0eP1Y4k5p9jI8JoGhSCCoMRMGMBgLFQt9/kyliVFDmUg8taDGTHRAP+U4f6b0E6NGT03RGByh43xCPqrjhnoXbhB5UpMhPrV1I5Ido8aNcQ28tqxHBu+nHMbkDeTJUKC+HYMXdJHuKemZYeJ4GhwJQ3apGDQlR4ycevrSvS/8yNI4nyv1slIH5XtxDi/AOJtDEUpWVCH0jE226IhOJNQ1h36WuZyozlvJgX6Oc0gqP2hInuF55mPM8PuR+bN9xvXyfP8M1+gjuqcmdXD8VbeFJvZ7IB9jFuT9M3hq1TgX01OT9tGfNaMvcFxoYtfPzzEcgJvR3zRIWfQzqzFS9XO9Xth8XVY+cVyjMZiSmSF1e3t75Xqe0uWEzddlhYmH9tBU4zLEWF5e/nYcv6DSEKoJ118rYyZ5bW1tH0KgjJkYuayhkzQjD9FoN1yA9okTJ8ocXoeSrIwZjtv1ocTbb799jGbMpHy2jqRJnqrPkASGOoF8jJkwgQFYqNjAOG1XcacQv828PbV8jJno4DZ/5qRfEp6aYcymof1pRtyiSth8i7A8DsSYwZCVy64Mmy4mbL4uK0w8MoMmSuDC78eTy58halnpiONx+mIReEB1SFPbI4jIrrbbVCTqUFYxTZ48+TXoaHm9ABejTF8scvbsWXMosrKy8rjsShesfhowFKnyGJIACZwjACO2ULHA7327iruF8EpCjRy4yXVLh06u82dudZhe/AQiM2hYTTgCbudf4kniv3Da5s1iILjcWCzyLpSZgJv9FiO9C17d47LjWM3BfUjKGPmRBZBZiuXCk2RRCJ4eLeeNp45KY7HISBkOxY9rtDSMMHPppZeelF3ihjJjpExkilEQCRQxARn2k+E/pSIMQTmOm/B7+ohKcwpRbqFKxwPkdhV3CkUWym8R2Spf2vQz5CjDfjL8p+qh/0nL8KAME6o0pxBlPOfP9DpJDDmif1mNNg/JbsR1FbLDkGHyLcLyOJBhRjz398gucbuIsPl2efkeh34qwpDEt3EjvhUKvBe7uSQeN6R4QZuQt0hLF6P1H9hlyFHGybfgpl0qccjZjLJLJI7t0xiG+Idz0XB/ly9fPg2wh0PKSLnZbdLEUFWrdDFaiJ9GmeywIgxtK7zOvVIHN/UsGOXsjwQX9ZC+YtMmk4dFRACdpXoQyWqF+8p+D2TToy7nFwHatcxJQj/HOcSoy/nVT5ULMvSY5PyZ0i/I0GOxzZ+pc2AYnoDFU8lHHIzQ3aj3fuymMUNcnjRugrFagaenGxE/il02KZM1ZtmjVOphI5RAj9dp6aGi3d3dk2CkRimjJcLkKQMvUe9B57EP6XtgyHol3ShjzpHB4JpDjXocBpLDjgKM2wVDIIin5nf+DEY61GIQHX4QT83v/FkSnpl+DoyHJxDaoNlU2IGO/y9HjBgxGz+ApyXPZbFIthqM4ZPyZCy7xDVZVyFN3mGLdIMh68R82MG5c+e+9Mgjj5wR4TBqAxaLqEZhDGdDj2tll7hKR1gl76lpx4ySwJAn4NeooQ9YqGDgd71dxfUQv6nIjJmS69eoQSdzSgS62uf7s+JozBTVwRWGNmi4Ib6EU16O4bk5MA5X4KZ/wP5WviwWQZl3Y3/OLx7IjWpxyBtocx+M7A4ME+7YsGHDUfs3J41P3uxGOXMFZC49+U5aLkLMH4oE3IyafM5KnS8MxkIVd5o/wxL0+fh9my9US1kc+5ozU3LdQjejJp+zUnVyzZ/B2FbJPJw+qiPzdCJbyWBYnAQc5xPiUNXj3TO35mJ7J82pQfwIHd89cyoraTJMiRs81nfS3Npmun8C6Jwsc2j+a/oriYe4UL8h8f79tZRfKejnOCeXn7TztfQ5Nd0Y+Z0/c6t/voVwMX1OTTdGfufP3OqH04q14yZgvmQcd0O2d8+exA/tA05t4gf+70iXOTn1Tto/O5WLOk1/9wzG6gxebNzj1AaeLufgyU3m5NQ7aZYvjDjVYRoJDDUC4qnBKGVPS+Lq/PzOn7nVV3LChuJNwShlxeield/5M7f6YfVi/XgJJGbQ4AHVqVOBwXhExe2h5MFYiEGTT+fUIUjEoOnvnqF9czGI6KFvRl52ya9RhwZNB8T4BUNAN2TqpOGtuX6/UZVRoVN9lRdFqBsyJQ99Ss75M1XWqb7KY1icBELPofk5LXhd5rtnuOFb8cWOJ9zqSZ6UkXyEt0hdt7JRpevvnkFmH/63m6uRMvL6pG0Y39F8Jy2qq0A5Q4EADMZCdR5O82cqr1BhrvmzQunFdqMhEGr8368KGKb7NDyb7xnl/xHDjWu86sKIrUX+J6UMjMZnMPz3917lw+bJC9dYij/NkHMM+h3wkgn9piM/a2j5TpoXKeaRAAmQQHIEEvHQ9OFGPLW5Djeq09bL6HVVftSh/l4ZPlLsOtyo2tXL6HVVPkMSIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESGKwE0oNV8aGq92uvvZaJ89wuvfTSUNd8//7918ap34wZM56NUz5lkwAJDF0CJUP31HhmJEACJEACFxIBGrQL6WrzXEmABEhgCBOgQRvCF5enRgIkQAIXEoGyOE520aJFEyD389jfg33Otm3barzaCVreS5afvNWrV5efPXt2Un9//8je3t5K6PecV72g5b1kRZF3+PDh1AMPPGAR9alPfSo1depUS1qhDg4cOOCo3/Tp0wulEtslARK4AAhEbtBqa2v/DIZiI9iN9MMvaHk/Mr3K1NXVjT19+vTMvr4+X95p0PJebUeV9+yzA9dNSFqxGLQ//OEPA05V0mjQBmBhAgmQQIQEIjVoixcvfi+M2VboVyE6ptPpdRUVFV930zdoeTc5ftNXrVo1Cp7ZLOioVvodq66ubnarH7S8m5wo02GIU889N9ChlLRbbrklVVpaGmVzgWX19PSkXnzxxQH1JO1DH/pQqry8fEAeE0iABLwJjFtx2HP188kNU1Wf5i0oZG4uPQaKT+8vSaV/MnbspHteXZvuGpgfbUpkBg3DhtKTPog9a8wQ/rapqemTMGqOFyJo+bCnnclk0suWLZuujFlZWdnZTZs2HXTTL2j5sPr5rb9r164UjHK2uPLIZAhS0iRvwYIFfkXFUk50OHXqVFa28shkCFLSJO8tb3lLLO1GJbS+vn6iyEJ4NCqZUcr5wQ9+kH0iuPPOO3uilEtZJBAPgcyM/lTmMydP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VSp27NgxTQnDMOHxMWPG7JIhQ5WmhximPIrjl5E/wDhDRzHI+6L8yr5qW7fqKo0hCZAACZBATATgVaXx+ag/QPxVWhP3whB9TR3Da6tAx38zvJp3I03iexD+BwyehPLVEFl08Uns02F85MXm38HA/Ezm4yQ/is3QU96Py3qQIhOGqhlf+zeNqXhtr7/+unx8eCSGJtNY/NGFMqcbGxuzhk7OA9tEyKrAufSgzFn8r7Y2mY+LQke7DBo0OxEekwAJkEDMBLCwYjbmop5BR69/eeNHMAir8RmpwC9Ew3B8ECr/GkaxPUrVjU9dzYNM8zNWMK5t8+fP3w+jZA59+m0TespnsdqhZ2QvU+ttm0rqiYyTAAmQAAnER+DFF188CU/lWXhWS9GK6ocvhxdzB9JHX3nllbteeuml7Ff43bQQD2r37t0LYVxkwUg9ZHVgWPBXbuXzSX/uued6r7766jfR1jhpT2QgrDx27NgE6FmKvevll1/2NE5S7+DBg6Og5wyc3xSsiOx/4YUXIjW86tzooSkSDEmABEggYQIYenwvOvxtaHaiQ9MvI+3XMFSHUOY4PCMZpqtCXIzLfKRfj/BirV4b3hObieE+c4Wilhcqavwjz1kwSOZ7bkqgzKNBl3bo143VjlmvDWkl0K0UexXSR8AbLVflEfbBEL6Uj4enyXCM0qA5YmEiCZAACSRDAP8j7WIYCvmnnjeFbHEf5q8+ijmuP4aU41hd5sNgnC6BrpbVio6FvRO78f7da1HO96nmaNAUCYYkQAIkUEAC8NZugFGThSHvCaIGvKPnUe8HMBIPyftsQermU1a8NXwJZCrqmv9ixqcc+Wr/Mby6cBw66++x+ayeuxgNWm5GLEECJEACiRFYvnz5NAzRfRBG6gPYZ6JhGY6cYChwCsbgOOIvYn8WHtm/RfmlDaMNX4F4bBhaHA19RmP14jAZjoQHp4YW+xDvRV4HzuEszuc0FoKY/4bGVwMsRAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAKDgMD/D2WyCk5hENCOAAAAAElFTkSuQmCC); + background-size: 218px 188px; + display: inline-block; + } +} + +.tui-toolbar-icons.tui-heading { + background-position: -172px -48px; +} + +.tui-toolbar-icons.tui-heading:disabled { + background-position: -193px -48px; +} + +.tui-toolbar-icons.tui-bold { + background-position: -4px -4px; +} + +.tui-toolbar-icons.tui-bold:disabled { + background-position: -25px -4px; +} + +.tui-toolbar-icons.tui-italic { + background-position: -4px -48px; +} + +.tui-toolbar-icons.tui-italic:disabled { + background-position: -25px -48px; +} + +.tui-toolbar-icons.tui-color { + background-position: -172px -70px; +} + +.tui-toolbar-icons.tui-color:disabled { + background-position: -193px -70px; +} + +.tui-toolbar-icons.tui-strike { + background-position: -4px -26px; +} + +.tui-toolbar-icons.tui-strike:disabled { + background-position: -25px -26px; +} + +.tui-toolbar-icons.tui-hrline { + background-position: -46px -92px; +} + +.tui-toolbar-icons.tui-hrline:disabled { + background-position: -67px -92px; +} + +.tui-toolbar-icons.tui-quote { + background-position: -4px -114px; +} + +.tui-toolbar-icons.tui-quote:disabled { + background-position: -25px -114px; +} + +.tui-toolbar-icons.tui-ul { + background-position: -46px -4px; +} + +.tui-toolbar-icons.tui-ul:disabled { + background-position: -67px -4px; +} + +.tui-toolbar-icons.tui-ol { + background-position: -46px -26px; +} + +.tui-toolbar-icons.tui-ol:disabled { + background-position: -67px -26px; +} + +.tui-toolbar-icons.tui-task { + background-position: -130px -48px; +} + +.tui-toolbar-icons.tui-task:disabled { + background-position: -151px -48px; +} + +.tui-toolbar-icons.tui-indent { + background-position: -46px -48px; +} + +.tui-toolbar-icons.tui-indent:disabled { + background-position: -67px -48px; +} + +.tui-toolbar-icons.tui-outdent { + background-position: -46px -70px; +} + +.tui-toolbar-icons.tui-outdent:disabled { + background-position: -67px -70px; +} + +.tui-toolbar-icons.tui-table { + background-position: -88px -92px; +} + +.tui-toolbar-icons.tui-table:disabled { + background-position: -109px -92px; +} + +.tui-toolbar-icons.tui-image { + background-position: -130px -4px; +} + +.tui-toolbar-icons.tui-image:disabled { + background-position: -151px -4px; +} + +.tui-toolbar-icons.tui-link { + background-position: -130px -26px; +} + +.tui-toolbar-icons.tui-link:disabled { + background-position: -151px -26px; +} + +.tui-toolbar-icons.tui-code { + background-position: -130px -92px; +} + +.tui-toolbar-icons.tui-code:disabled { + background-position: -151px -92px; +} + +.tui-toolbar-icons.tui-codeblock { + background-position: -130px -70px; +} + +.tui-toolbar-icons.tui-codeblock:disabled { + background-position: -151px -70px; +} + +.tui-toolbar-icons.tui-more { + background-position: -172px -92px; +} + +.tui-toolbar-icons.tui-more:disabled { + background-position: -193px -92px; +} +.tui-colorpicker-svg-slider { + border: 1px solid #ebebeb; +} +.tui-colorpicker-vml-slider { + border: 1px solid #ebebeb; +} +.tui-colorpicker-svg-huebar { + border: 1px solid #ebebeb; +} + +.tui-editor-pseudo-clipboard { + position: fixed; + left: -1000px; + top: -1000px; + width: 100px; + height: 100px; +} + +.te-ww-block-overlay.code-block-header { + text-align: right; + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +.te-ww-block-overlay.code-block-header span { + font-size: 10px; + font-weight: 600; + padding: 0px 10px; + color: #333333; + cursor: default; +} + +.te-ww-block-overlay.code-block-header button { + margin: 8px; + font-size: 10px; + color: #333333; + background-color: #f9f9f9; + border: 1px solid #dddddd; + padding: 4px; + height: auto; +} + +.te-popup-code-block-languages { + position: fixed; + box-sizing: border-box; + width: 130px; +} + +.te-popup-code-block-languages .tui-popup-body { + max-height: 169px; + overflow: auto; + padding: 0px; +} + +.te-popup-code-block-languages button { + width: 100%; + background-color: #fff; + border: none; + outline: 0; + padding: 0px 10px 0px 10px; + font-size: 12px; + line-height: 24px; + text-align: left; + color: #777; +} + +.te-popup-code-block-languages button.active { + background-color: #f4f4f4; +} + +.tui-popup-code-block-editor .tui-popup-wrapper { + width: 70%; + height: 70%; + margin: auto; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; +} + +.te-input-language { + position: relative; + margin-left: 15px; + cursor: pointer; +} + +.te-input-language input { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: 10px; + padding: 3px 5px; + border: 1px solid #dddddd; + background-color: #f9f9f9; + box-sizing: border-box; + width: 130px; + outline: none; +} + +.te-input-language input::-ms-clear { + display: none; +} + +.te-input-language::after { + content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxMnB4IiBoZWlnaHQ9IjE0cHgiIHZpZXdCb3g9IjAgMCAxMiAxNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT42Q0NBRDk2QS0yMjYxLTRFNDAtOTk1RC1DRUUyQUREQUQ3NkQ8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbS10cmFuZ2xlLWQtc2lkZSIgZmlsbD0iIzU1NTU1NSI+ICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlJlY3RhbmdsZS03IiBwb2ludHM9IjIgNSAxMCA1IDYgMTAiPjwvcG9seWdvbj4gICAgICAgIDwvZz4gICAgPC9nPjwvc3ZnPg==); + position: absolute; + top: 1px; + right: 3px; +} + +.te-input-language.active::after { + content: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxMnB4IiBoZWlnaHQ9IjE0cHgiIHZpZXdCb3g9IjAgMCAxMiAxNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT5BNEZDRkIzMy0zNjdBLTREMjAtOEEyNC1DQ0I2ODFBMDZDODg8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbS10cmFuZ2xlLXVwLXNpZGUiIGZpbGw9IiM1NTU1NTUiPiAgICAgICAgICAgIDxwb2x5Z29uIGlkPSJSZWN0YW5nbGUtNyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNi4wMDAwMDAsIDYuNTAwMDAwKSBzY2FsZSgxLCAtMSkgdHJhbnNsYXRlKC02LjAwMDAwMCwgLTYuNTAwMDAwKSAiIHBvaW50cz0iMiA0IDEwIDQgNiA5Ij48L3BvbHlnb24+ICAgICAgICA8L2c+ICAgIDwvZz48L3N2Zz4=); +} + +.tui-popup-code-block-editor button { + margin: -1px 3px; +} + +.tui-popup-code-block-editor .tui-popup-header-buttons { + height: 20px; +} + +.tui-popup-code-block-editor .popup-editor-toggle-preview::after { + content: 'Preview off'; + color: #777; + margin-right: 22px; +} + +.tui-popup-code-block-editor .popup-editor-toggle-preview.active::after { + content: 'Preview on'; + color: #4b96e6; +} + +.tui-popup-code-block-editor .popup-editor-toggle-scroll::after { + content: 'Scroll off'; + color: #777; + margin-right: 16px; +} + +.tui-popup-code-block-editor .popup-editor-toggle-scroll.active::after { + content: 'Scroll on'; + color: #4b96e6; +} + +.tui-popup-code-block-editor .popup-editor-toggle-fit { + width: 18px; + height: 18px; + margin-top: 4px; + margin-right: 14px; + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCAxOCAxOCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT40OUQ4RTYyMy1GRTAyLTQ1RUUtQkQ5Ri0xMjUyQjEzRTU1MkQ8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbnRlbnRzLWV4cGFuZCIgZmlsbD0iIzU1NTU1NSI+ICAgICAgICAgICAgPHBhdGggZD0iTTMsMyBMOSwzIEw5LDUgTDUsNSBMNSw5IEwzLDkgTDMsMyBaIE0xNSwxNSBMOSwxNSBMOSwxMyBMMTMsMTMgTDEzLDkgTDE1LDkgTDE1LDE1IFoiIGlkPSJDb21iaW5lZC1TaGFwZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS4wMDAwMDAsIDkuMDAwMDAwKSBzY2FsZSgtMSwgMSkgdHJhbnNsYXRlKC05LjAwMDAwMCwgLTkuMDAwMDAwKSAiPjwvcGF0aD4gICAgICAgICAgICA8cG9seWdvbiBpZD0iTGluZSIgZmlsbC1ydWxlPSJub256ZXJvIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMS41MDAwMDAsIDYuNTAwMDAwKSBzY2FsZSgtMSwgMSkgdHJhbnNsYXRlKC0xMS41MDAwMDAsIC02LjUwMDAwMCkgIiBwb2ludHM9IjkuMDg1Nzg2NDQgNS41IDEyLjUgOC45MTQyMTM1NiAxMy45MTQyMTM2IDcuNSAxMC41IDQuMDg1Nzg2NDQiPjwvcG9seWdvbj4gICAgICAgICAgICA8cG9seWdvbiBpZD0iTGluZS1Db3B5IiBmaWxsLXJ1bGU9Im5vbnplcm8iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDYuNTAwMDAwLCAxMS41MDAwMDApIHNjYWxlKC0xLCAxKSB0cmFuc2xhdGUoLTYuNTAwMDAwLCAtMTEuNTAwMDAwKSAiIHBvaW50cz0iNC4wODU3ODY0NCAxMC41IDcuNSAxMy45MTQyMTM2IDguOTE0MjEzNTYgMTIuNSA1LjUgOS4wODU3ODY0NCI+PC9wb2x5Z29uPiAgICAgICAgPC9nPiAgICA8L2c+PC9zdmc+); +} + +.tui-popup-code-block-editor .popup-editor-toggle-fit.active { + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiIHZpZXdCb3g9IjAgMCAxOCAxOCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4gICAgICAgIDx0aXRsZT4wN0Q1MjlCRi1GNTIzLTREN0EtQTlGNi05NTUzNTU5RDNEMUE8L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggc2tldGNodG9vbC48L2Rlc2M+ICAgIDxkZWZzPjwvZGVmcz4gICAgPGcgaWQ9IlN5bWJvbHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPiAgICAgICAgPGcgaWQ9ImNvbnRlbnRzLXJlZHVjZSIgZmlsbD0iIzU1NTU1NSI+ICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgtMzIiIGZpbGwtcnVsZT0ibm9uemVybyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNS41MDAwMDAsIDEyLjUwMDAwMCkgc2NhbGUoLTEsIDEpIHRyYW5zbGF0ZSgtNS41MDAwMDAsIC0xMi41MDAwMDApICIgcG9pbnRzPSIzLjA4NTc4NjQ0IDExLjUgNi41IDE0LjkxNDIxMzYgNy45MTQyMTM1NiAxMy41IDQuNSAxMC4wODU3ODY0Ij48L3BvbHlnb24+ICAgICAgICAgICAgPHBhdGggZD0iTTksOSBMMTUsOSBMMTUsMTEgTDExLDExIEwxMSwxNSBMOSwxNSBMOSw5IFogTTksOSBMMyw5IEwzLDcgTDcsNyBMNywzIEw5LDMgTDksOSBaIiBpZD0iQ29tYmluZWQtU2hhcGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMDAwMDAwLCA5LjAwMDAwMCkgc2NhbGUoLTEsIDEpIHRyYW5zbGF0ZSgtOS4wMDAwMDAsIC05LjAwMDAwMCkgIj48L3BhdGg+ICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgtMzMiIGZpbGwtcnVsZT0ibm9uemVybyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTIuNTAwMDAwLCA1LjUwMDAwMCkgc2NhbGUoLTEsIDEpIHRyYW5zbGF0ZSgtMTIuNTAwMDAwLCAtNS41MDAwMDApICIgcG9pbnRzPSIxNC45MTQyMTM2IDYuNSAxMS41IDMuMDg1Nzg2NDQgMTAuMDg1Nzg2NCA0LjUgMTMuNSA3LjkxNDIxMzU2Ij48L3BvbHlnb24+ICAgICAgICA8L2c+ICAgIDwvZz48L3N2Zz4=); +} + +.tui-popup-code-block-editor .tui-popup-close-button { + margin-top: 6px; +} + +.tui-popup-code-block-editor .tui-popup-body { + z-index: -1; + padding: 0px; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex: 1; + flex: 1; +} + +.tui-popup-code-block-editor .popup-editor-body { + position: relative; + -ms-flex: 1; + flex: 1; + border-bottom: 1px solid #cacaca; +} + +.tui-popup-code-block-editor .te-button-section { + padding: 15px; +} + +.tui-popup-code-block-editor .te-button-section button { + float: left; +} + +.tui-popup-code-block-editor .tui-editor-contents pre { + margin: 0px; + background-color: transparent; +} + +.tui-popup-code-block-editor .CodeMirror { + height: auto; +} + +.tui-popup-code-block-editor .CodeMirror-line { + font-family: Consolas, Courier, 'Lucida Grande', '나눔바른고딕', 'Nanum Barun Gothic', '맑은고딕', + 'Malgun Gothic', sans-serif; + font-size: 13px; + line-height: 160%; + letter-spacing: -0.3px; +} + +.tui-popup-code-block-editor .popup-editor-editor-wrapper { + min-height: 100%; +} + +.tui-split-scroll-wrapper { + position: relative; +} + +.tui-split-scroll { + position: absolute; +} + +.tui-split-scroll, +.tui-split-scroll-wrapper { + width: 100%; + height: 100%; +} + +.tui-split-scroll .tui-split-content-left, +.tui-split-scroll .tui-split-content-right { + position: absolute; + top: 0px; + width: 50%; + box-sizing: border-box; +} + +.tui-split-scroll .tui-split-content-left { + left: 0px; +} + +.tui-split-scroll .tui-split-content-right { + left: 50%; +} + +.tui-split-scroll .tui-splitter { + position: absolute; + left: 50%; + top: 0; + height: 100%; + width: 1px; + border-left: 1px solid #cacaca; +} + +.tui-split-scroll .tui-split-scroll-content { + width: 100%; + height: 100%; + overflow: hidden; + position: relative; +} + +.tui-split-scroll .tui-split-content-left, +.tui-split-scroll .tui-split-content-right { + height: 100%; + overflow-x: hidden; + overflow-y: auto; +} + +.tui-split-scroll button.tui-scrollsync { + top: 10px; + opacity: 0.2; +} + +.tui-split-scroll button.tui-scrollsync::after { + content: 'scroll off'; +} + +.tui-split-scroll.scroll-sync button.tui-scrollsync { + opacity: 0.5; +} + +.tui-split-scroll.scroll-sync .tui-split-content-left, +.tui-split-scroll.scroll-sync .tui-split-content-right { + height: auto; + overflow: initial; +} + +.tui-split-scroll.scroll-sync button.tui-scrollsync::after { + content: 'scroll on'; +} + +.tui-split-scroll.scroll-sync .tui-split-scroll-content { + overflow-y: auto; +} + +.tui-split-scroll.single-content .tui-splitter { + display: none; +} + +.tui-split-scroll.single-content .tui-split-content-left { + width: 100%; +} + +.tui-split-scroll.single-content .tui-split-content-right { + display: none; +} + +.tui-split-scroll.single-content button.tui-scrollsync { + display: none; +} + +@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { + /* IE10+ */ + .tui-split-scroll-wrapper .tui-splitter { + left: calc(50% - 9px); + } +} + +@supports (-ms-accelerator: true) { + /* IE Edge 12+ CSS styles go here */ + .tui-split-scroll-wrapper .tui-splitter { + left: calc(50% - 9px); + } +} + +@media screen and (max-width: 480px) { + .tui-popup-wrapper { + max-width: 300px; + } + + .tui-editor-popup { + margin-left: -150px; + } + + .te-dropdown-toolbar { + max-width: none; + } +} + +@charset "utf-8"; +.tui-editor-contents { + margin: 0; + padding: 0; + font-size: 13px; + font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', 'Arial', '나눔바른고딕', + 'Nanum Barun Gothic', '맑은고딕', 'Malgun Gothic', sans-serif; +} + +.tui-editor-contents *:not(table) { + line-height: 160%; + box-sizing: content-box; +} + +.tui-editor-contents i, +.tui-editor-contents cite, +.tui-editor-contents em, +.tui-editor-contents var, +.tui-editor-contents address, +.tui-editor-contents dfn { + font-style: italic; +} + +.tui-editor-contents strong { + font-weight: bold; +} + +.tui-editor-contents p { + margin: 10px 0; + color: #222; +} + +.tui-editor-contents > h1:first-of-type, +.tui-editor-contents > div > div:first-of-type h1 { + margin-top: 14px; +} + +.tui-editor-contents h1, +.tui-editor-contents h2, +.tui-editor-contents h3, +.tui-editor-contents h4, +.tui-editor-contents h5, +.tui-editor-contents h6 { + font-weight: bold; + color: #222; +} + +.tui-editor-contents h1 { + font-size: 24px; + line-height: 28px; + border-bottom: 3px double #999; + margin: 52px 0 15px 0; + padding-bottom: 7px; +} + +.tui-editor-contents h2 { + font-size: 22px; + line-height: 23px; + border-bottom: 1px solid #dbdbdb; + margin: 20px 0 13px 0; + padding-bottom: 7px; +} + +.tui-editor-contents h3 { + font-size: 20px; + margin: 18px 0 2px; +} + +.tui-editor-contents h4 { + font-size: 18px; + margin: 10px 0 2px; +} + +.tui-editor-contents h3, +.tui-editor-contents h4 { + line-height: 18px; +} + +.tui-editor-contents h5 { + font-size: 16px; +} + +.tui-editor-contents h6 { + font-size: 14px; +} + +.tui-editor-contents h5, +.tui-editor-contents h6 { + line-height: 17px; + margin: 9px 0 -4px; +} + +.tui-editor-contents del { + color: #999; +} + +.tui-editor-contents blockquote { + margin: 14px 0; + border-left: 4px solid #e5e5e5; + padding: 0 16px; + color: #999; +} + +.tui-editor-contents blockquote p, +.tui-editor-contents blockquote ul, +.tui-editor-contents blockquote ol { + color: #999; +} + +.tui-editor-contents blockquote > :first-child { + margin-top: 0; +} + +.tui-editor-contents blockquote > :last-child { + margin-bottom: 0; +} + +.tui-editor-contents pre, +.tui-editor-contents code { + font-family: Consolas, Courier, 'Apple SD 산돌고딕 Neo', -apple-system, 'Lucida Grande', + 'Apple SD Gothic Neo', '맑은 고딕', 'Malgun Gothic', 'Segoe UI', '돋움', dotum, sans-serif; + border: 0; + border-radius: 0; +} + +.tui-editor-contents pre { + margin: 2px 0 8px; + padding: 18px; + background-color: #f5f7f8; +} + +.tui-editor-contents code { + color: #c1798b; + background-color: #f9f2f4; + padding: 2px 3px; + letter-spacing: -0.3px; + border-radius: 2px; +} + +.tui-editor-contents pre code { + padding: 0; + color: inherit; + white-space: pre-wrap; + background-color: transparent; +} + +.tui-editor-contents pre.addon { + border: 1px solid #e8ebed; + background-color: #fff; +} + +.tui-editor-contents img { + margin: 4px 0 10px; + box-sizing: border-box; + vertical-align: top; + max-width: 100%; +} + +.tui-editor-contents table { + border: 1px solid rgba(0, 0, 0, 0.1); + margin: 12px 0 14px; + color: #222; + width: auto; + border-collapse: collapse; + box-sizing: border-box; +} + +.tui-editor-contents table th, +.tui-editor-contents table td { + border: 1px solid rgba(0, 0, 0, 0.1); + padding: 5px 14px 5px 12px; + height: 32px; +} + +.tui-editor-contents table th { + background-color: #555; + font-weight: 300; + color: #fff; + padding-top: 6px; +} + +.tui-editor-contents ul, +.tui-editor-contents menu, +.tui-editor-contents ol, +.tui-editor-contents dir { + display: block; + list-style-type: none; + padding-left: 24px; + margin: 6px 0 10px; + color: #222; +} + +.tui-editor-contents ol { + list-style-type: none; + counter-reset: li; +} + +.tui-editor-contents ol > li { + counter-increment: li; +} + +.tui-editor-contents ul > li::before, +.tui-editor-contents ol > li::before { + display: inline-block; + position: absolute; +} + +.tui-editor-contents ul > li::before { + content: ''; + margin-top: 6px; + margin-left: -17px; + width: 5px; + height: 5px; + border-radius: 50%; + background-color: #ccc; +} + +.tui-editor-contents ol > li::before { + content: '.' counter(li); + margin-left: -28px; + width: 24px; + text-align: right; + direction: rtl; + color: #aaa; +} + +.tui-editor-contents ul ul, +.tui-editor-contents ul ol, +.tui-editor-contents ol ol, +.tui-editor-contents ol ul { + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +.tui-editor-contents ul li, +.tui-editor-contents ol li { + position: relative; +} + +.tui-editor-contents ul p, +.tui-editor-contents ol p { + margin: 0; +} + +.tui-editor-contents ul li.task-list-item::before, +.tui-editor-contents ol li.task-list-item::before, +.tui-editor-contents pre ul li::before { + content: ''; +} + +.tui-editor-contents th ol, +.tui-editor-contents th ul { + color: #fff; +} + +.tui-editor-contents hr { + border-top: 1px solid #eee; + margin: 16px 0; +} + +.tui-editor-contents a { + text-decoration: underline; + color: #4b96e6; +} + +.tui-editor-contents a:hover { + color: #1f70de; +} + +.tui-editor-contents a.image-link { + position: relative; +} + +.tui-editor-contents a.image-link::before { + content: ''; + position: absolute; + margin: 0; + width: 20px; + height: 20px; + top: 2px; + right: 2px; + background-repeat: no-repeat; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAFKADAAQAAAABAAAAFAAAAACy3fD9AAAA/0lEQVQ4Ee2UIY6FQAyG/91wAQQJDg8SSwI3QIFAcQHuwFHQoOAEEFAELB6H4wIku+9vQgIP9zLyVbTTTufLtJ3MzzRNf1AoGlmu6ypBzvOMXyWkC+QLvDTjw6VM+Xr2OA6UZYmu67Dvu2zleX6zuq7D933EcQxNuyPu3usYYXVdw/M8mKYpIMMwxEZRJHbbNsmhkySJxE71APJmhGVZhnVdURQFlmU585GmKSzLEp+570Dlz+ZxQ/aGJVNYsm3bCIJA/LZtMY4jmqbBMAwIw1DiV/UAstEUltP3vawdxxFbVZVYDoWwM1eCp+LnoErIUt7DL/Ac1edWng1/WlXyD380myY5A34sAAAAAElFTkSuQmCC'); + cursor: pointer; +} + +.tui-editor-contents .task-list-item { + border: 0; + list-style: none; + padding-left: 24px; + margin-left: -24px; +} + +.tui-editor-contents .task-list-item::before { + background-repeat: no-repeat; + background-size: 18px 18px; + background-position: center; + content: ''; + margin-left: 0; + margin-top: 0; + border-radius: 0; + height: 18px; + width: 18px; + position: absolute; + left: 0; + top: 1px; + cursor: pointer; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAEqADAAQAAAABAAAAEgAAAACaqbJVAAAAQklEQVQ4EWM8c+bMfwYqABaQGcbGxhQZdfbsWQYmikxA0jxqEFJg4GCOhhGOgEESHg0jpMDAwRx8YQQuj0DlCaUAAEdBCPJ7TaEPAAAAAElFTkSuQmCC'); +} + +.tui-editor-contents .task-list-item.checked::before { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAEqADAAQAAAABAAAAEgAAAACaqbJVAAAA1ElEQVQ4EWP0nvbsPwMVABMVzAAbMWoQIiT5OJgYvLS5EAJQFguGCB4BkCHt/kIM8kKsYFXbrn6DqyY6sJENefjuN8ORuz/ghoAYWA0COR2kEQbQDanc+I7h049/MGkwjVANFQYZkmXHD/YCyABiDAFpxQgjkJO9dbjA4QAKDxAAhQnIO9hcAlYAJDBcBHIySANII8gAYgwBGYZhEEgQZFjVJohhhFwCUg8CjPgyLT8nE8N/YJZGD1iIVlQSI4yQpT9+R40ZZDl0NlavoSsihj/4DAIAR+hZHUj727YAAAAASUVORK5CYII='); +} + +.tui-editor-contents .task-list-item input[type='checkbox'], +.tui-editor-contents .task-list-item .task-list-item-checkbox { + margin-left: -17px; + margin-right: 3.8px; + margin-top: 3px; +} + +.tui-editor-contents-placeholder::before { + content: attr(data-placeholder); + color: grey; + line-height: 160%; + position: absolute; +} + +.te-preview .tui-editor-contents h1 { + min-height: 28px; +} + +.te-preview .tui-editor-contents h2 { + min-height: 23px; +} + +.te-preview .tui-editor-contents blockquote { + min-height: 20px; +} + +.te-preview .tui-editor-contents li { + min-height: 22px; +} + +@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { + /* IE10+11 */ + .te-ww-container .tui-editor-contents li { + vertical-align: middle; + } + + .te-ww-container .tui-editor-contents ul > li::before, + .te-ww-container .tui-editor-contents ol > li::before, + .te-ww-container .tui-editor-contents .task-list-item:before { + position: static; + vertical-align: middle; + } + + .te-ww-container .tui-editor-contents ul > li::before { + margin-top: -3px; + margin-right: 12px; + } + + .te-ww-container .tui-editor-contents ol > li::before { + margin-right: 6px; + } + + .te-ww-container .tui-editor-contents .task-list-item { + padding-left: 2px; + } +} + +.tui-editor-contents .te-preview-highlight { + position: relative; + z-index: 0; +} + +.tui-editor-contents .te-preview-highlight::after { + content: ''; + background-color: rgba(255, 245, 131, 0.5); + border-radius: 4px; + z-index: -1; + position: absolute; + top: -4px; + right: -4px; + left: -4px; + bottom: -4px; +} + +.tui-editor-contents h1.te-preview-highlight::after, +.tui-editor-contents h2.te-preview-highlight::after { + bottom: 0; +} + +.tui-editor-contents td.te-preview-highlight::after, +.tui-editor-contents th.te-preview-highlight::after { + display: none; +} + +.tui-editor-contents th.te-preview-highlight, +.tui-editor-contents td.te-preview-highlight { + background-color: rgba(255, 245, 131, 0.5); +} + +.tui-editor-contents th.te-preview-highlight { + color: #222; +} + +.te-md-container .CodeMirror { + font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', 'Arial', '나눔바른고딕', + 'Nanum Barun Gothic', '맑은고딕', 'Malgun Gothic', sans-serif; + color: #222; +} + +.tui-md-heading1 { + font-size: 24px; +} + +.tui-md-heading2 { + font-size: 22px; +} + +.tui-md-heading3 { + font-size: 20px; +} + +.tui-md-heading4 { + font-size: 18px; +} + +.tui-md-heading5 { + font-size: 16px; +} + +.tui-md-heading6 { + font-size: 14px; +} + +.tui-md-heading.tui-md-delimiter.setext { + line-height: 15px; +} + +.tui-md-strong, +.tui-md-heading, +.tui-md-list-item.tui-md-list-item-bullet, +.tui-md-list-item.tui-md-meta { + font-weight: bold; +} + +.tui-md-emph { + font-style: italic; +} + +.tui-md-strike { + text-decoration: line-through; +} + +.tui-md-strike.tui-md-delimiter { + text-decoration: none; +} + +.tui-md-delimiter, +.tui-md-thematic-break, +.tui-md-link, +.tui-md-table, +.tui-md-block-quote { + color: #ccc; +} + +.tui-md-code-block.tui-md-meta, +.tui-md-code.tui-md-delimiter { + color: #aaa; +} + +.tui-md-meta, +.tui-md-html, +.tui-md-link.tui-md-link-url.tui-md-marked-text { + color: #999; +} + +.tui-md-block-quote.tui-md-marked-text, +.tui-md-list-item.tui-md-meta { + color: #555; +} + +.tui-md-table.tui-md-marked-text { + color: #222; +} + +.tui-md-link.tui-md-link-desc.tui-md-marked-text, +.tui-md-list-item-odd.tui-md-list-item-bullet { + color: #4b96e6; +} + +.tui-md-list-item-even.tui-md-list-item-bullet { + color: #cb4848; +} + +.tui-md-code.tui-md-marked-text { + color: #c1798b; +} + +.tui-md-code { + background-color: rgba(243, 229, 233, 0.5); + padding: 2px 0; + letter-spacing: -0.3px; +} + +.tui-md-code.tui-md-delimiter.start { + padding-left: 2px; + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; +} + +.tui-md-code.tui-md-delimiter.end { + padding-right: 2px; + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; +} + +.tui-md-code-block.CodeMirror-linebackground { + left: 20px; + right: 20px; + background-color: #f5f7f8; +} + +.tui-md-code-block.CodeMirror-linebackground.start { + top: 2px; +} + +.tui-md-code-block.CodeMirror-linebackground.end { + bottom: 2px; +} + +.tui-md-code, +.tui-md-code-block { + font-family: Consolas, Courier, 'Lucida Grande', '나눔바른고딕', 'Nanum Barun Gothic', '맑은고딕', + 'Malgun Gothic', sans-serif; +} + diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor.js new file mode 100644 index 0000000000..1ecaa485bc --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/toastui-editor.js @@ -0,0 +1,29366 @@ +/*! + * @toast-ui/editor + * @version 2.5.1 | Tue Nov 24 2020 + * @author NHN FE Development Lab + * @license MIT + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("codemirror")); + else if(typeof define === 'function' && define.amd) + define(["codemirror"], factory); + else if(typeof exports === 'object') + exports["Editor"] = factory(require("codemirror")); + else + root["toastui"] = root["toastui"] || {}, root["toastui"]["Editor"] = factory(root["CodeMirror"]); +})(window, function(__WEBPACK_EXTERNAL_MODULE__15__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 65); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); +/* harmony import */ var tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9); +/* harmony import */ var tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var tui_code_snippet_domUtil_css__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4); +/* harmony import */ var tui_code_snippet_domUtil_css__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_css__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5); +/* harmony import */ var tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_4__); +/* harmony import */ var tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6); +/* harmony import */ var tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_5__); +/* harmony import */ var tui_code_snippet_domUtil_hasClass__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(16); +/* harmony import */ var tui_code_snippet_domUtil_hasClass__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_hasClass__WEBPACK_IMPORTED_MODULE_6__); +/* harmony import */ var tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(13); +/* harmony import */ var tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7__); +/** + * @fileoverview DOM Utils + * @author NHN FE Development Lab + */ + + + + + + + + +var FIND_ZWB = /\u200B/g; +var _window = window, + getComputedStyle = _window.getComputedStyle; +/** + * Check if node is text node + * @param {Node} node node to check + * @returns {boolean} result + * @ignore + */ + +var isTextNode = function isTextNode(node) { + return node && node.nodeType === Node.TEXT_NODE; +}; +/** + * Check if node is element node + * @param {Node} node node to check + * @returns {boolean} result + * @ignore + */ + + +var isElemNode = function isElemNode(node) { + return node && node.nodeType === Node.ELEMENT_NODE; +}; +/** + * Check that the node is block node + * @param {Node} node node + * @returns {boolean} + * @ignore + */ + + +var isBlockNode = function isBlockNode(node) { + return /^(ADDRESS|ARTICLE|ASIDE|BLOCKQUOTE|DETAILS|DIALOG|DD|DIV|DL|DT|FIELDSET|FIGCAPTION|FIGURE|FOOTER|FORM|H[\d]|HEADER|HGROUP|HR|LI|MAIN|NAV|OL|P|PRE|SECTION|UL)$/gi.test(this.getNodeName(node)); +}; +/** + * Get node name of node + * @param {Node} node node + * @returns {string} node name + * @ignore + */ + + +var getNodeName = function getNodeName(node) { + if (isElemNode(node)) { + return node.tagName; + } + + return 'TEXT'; +}; +/** + * Get node offset length of node(for Range API) + * @param {Node} node node + * @returns {number} length + * @ignore + */ + + +var getTextLength = function getTextLength(node) { + var len; + + if (isElemNode(node)) { + len = node.textContent.replace(FIND_ZWB, '').length; + } else if (isTextNode(node)) { + len = node.nodeValue.replace(FIND_ZWB, '').length; + } + + return len; +}; +/** + * Get node offset length of node(for Range API) + * @param {Node} node node + * @returns {number} length + * @ignore + */ + + +var getOffsetLength = function getOffsetLength(node) { + var len; + + if (isElemNode(node)) { + len = node.childNodes.length; + } else if (isTextNode(node)) { + len = node.nodeValue.replace(FIND_ZWB, '').length; + } + + return len; +}; +/** + * get node offset between parent's childnodes + * @param {Node} node node + * @returns {number} offset(index) + * @ignore + */ + + +var getNodeOffsetOfParent = function getNodeOffsetOfParent(node) { + var childNodesOfParent = node.parentNode.childNodes; + var i, t, found; + + for (i = 0, t = childNodesOfParent.length; i < t; i += 1) { + if (childNodesOfParent[i] === node) { + found = i; + break; + } + } + + return found; +}; +/** + * get child node by offset + * @param {Node} node node + * @param {number} index offset index + * @returns {Node} foudned node + * @ignore + */ + + +var getChildNodeByOffset = function getChildNodeByOffset(node, index) { + var currentNode; + + if (isTextNode(node)) { + currentNode = node; + } else if (node.childNodes.length && index >= 0) { + currentNode = node.childNodes[index]; + } + + return currentNode; +}; +/** + * find next node from passed node + * @param {strong} direction previous or next + * @param {Node} node node + * @param {string} untilNodeName parent node name to limit + * @returns {Node} founded node + * @ignore + */ + + +var getNodeWithDirectionUntil = function getNodeWithDirectionUntil(direction, node, untilNodeName) { + var directionKey = direction + "Sibling"; + var nodeName, foundedNode; + + while (node && !node[directionKey]) { + nodeName = getNodeName(node.parentNode); + + if (nodeName === untilNodeName || nodeName === 'BODY') { + break; + } + + node = node.parentNode; + } + + if (node[directionKey]) { + foundedNode = node[directionKey]; + } + + return foundedNode; +}; +/** + * get prev node of childnode pointed with index + * @param {Node} node node + * @param {number} index offset index + * @param {string} untilNodeName parent node name to limit + * @returns {Node} founded node + * @ignore + */ + + +var getPrevOffsetNodeUntil = function getPrevOffsetNodeUntil(node, index, untilNodeName) { + var prevNode; + + if (index > 0) { + prevNode = getChildNodeByOffset(node, index - 1); + } else { + prevNode = getNodeWithDirectionUntil('previous', node, untilNodeName); + } + + return prevNode; +}; + +var getParentUntilBy = function getParentUntilBy(node, matchCondition, stopCondition) { + while (node.parentNode && !matchCondition(node.parentNode)) { + node = node.parentNode; + + if (stopCondition && stopCondition(node)) { + break; + } + } + + if (matchCondition(node.parentNode)) { + return node; + } + + return null; +}; +/** + * get parent node until paseed node name + * @param {Node} node node + * @param {string|HTMLNode} untilNode node name or node to limit + * @returns {Node} founded node + * @ignore + */ + + +var getParentUntil = function getParentUntil(node, untilNode) { + var foundedNode; + + if (tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default()(untilNode)) { + foundedNode = getParentUntilBy(node, function (targetNode) { + return untilNode === getNodeName(targetNode); + }); + } else { + foundedNode = getParentUntilBy(node, function (targetNode) { + return untilNode === targetNode; + }); + } + + return foundedNode; +}; +/** + * get node on the given direction under given parent + * @param {strong} direction previous or next + * @param {Node} node node + * @param {string|Node} underNode parent node name to limit + * @returns {Node} founded node + * @ignore + */ + + +var getNodeWithDirectionUnderParent = function getNodeWithDirectionUnderParent(direction, node, underNode) { + var directionKey = direction + "Sibling"; + var foundedNode; + node = getParentUntil(node, underNode); + + if (node && node[directionKey]) { + foundedNode = node[directionKey]; + } + + return foundedNode; +}; +/** + * get top previous top level node under given node + * @param {Node} node node + * @param {Node} underNode underNode + * @returns {Node} founded node + * @ignore + */ + + +var getTopPrevNodeUnder = function getTopPrevNodeUnder(node, underNode) { + return getNodeWithDirectionUnderParent('previous', node, underNode); +}; +/** + * get next top level block node + * @param {Node} node node + * @param {Node} underNode underNode + * @returns {Node} founded node + * @ignore + */ + + +var getTopNextNodeUnder = function getTopNextNodeUnder(node, underNode) { + return getNodeWithDirectionUnderParent('next', node, underNode); +}; +/** + * Get parent element the body element + * @param {Node} node Node for start searching + * @returns {Node} + * @ignore + */ + + +var getTopBlockNode = function getTopBlockNode(node) { + return getParentUntil(node, 'BODY'); +}; +/** + * Get previous text node + * @param {Node} node Node for start searching + * @returns {Node} + * @ignore + */ + + +var getPrevTextNode = function getPrevTextNode(node) { + node = node.previousSibling || node.parentNode; + + while (!isTextNode(node) && getNodeName(node) !== 'BODY') { + if (node.previousSibling) { + node = node.previousSibling; + + while (node.lastChild) { + node = node.lastChild; + } + } else { + node = node.parentNode; + } + } + + if (getNodeName(node) === 'BODY') { + node = null; + } + + return node; +}; +/** + * test whether root contains the given node + * @param {HTMLNode|string} root - root node + * @param {HTMLNode} found - node to test + * @returns {Boolean} true if root contains node + * @ignore + */ + + +var containsNode = function containsNode(root, node) { + var walker = document.createTreeWalker(root, 4, null, false); + var found = root === node; + + while (!found && walker.nextNode()) { + found = walker.currentNode === node; + } + + return found; +}; +/** + * find node by offset + * @param {HTMLElement} root Root element + * @param {Array.} offsetList offset list + * @param {function} textNodeFilter Text node filter + * @returns {Array} + * @ignore + */ + + +var findOffsetNode = function findOffsetNode(root, offsetList, textNodeFilter) { + var result = []; + var text = ''; + var walkerOffset = 0; + var newWalkerOffset; + + if (!offsetList.length) { + return result; + } + + var offset = offsetList.shift(); + var walker = document.createTreeWalker(root, 4, null, false); + + while (walker.nextNode()) { + text = walker.currentNode.nodeValue || ''; + + if (textNodeFilter) { + text = textNodeFilter(text); + } + + newWalkerOffset = walkerOffset + text.length; + + while (newWalkerOffset >= offset) { + result.push({ + container: walker.currentNode, + offsetInContainer: offset - walkerOffset, + offset: offset + }); + + if (!offsetList.length) { + return result; + } + + offset = offsetList.shift(); + } + + walkerOffset = newWalkerOffset; + } // there should be offset left + + + do { + result.push({ + container: walker.currentNode, + offsetInContainer: text.length, + offset: offset + }); + offset = offsetList.shift(); + } while (!tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(offset)); + + return result; +}; + +var getNodeInfo = function getNodeInfo(node) { + var path = {}; + path.tagName = node.nodeName; + + if (node.id) { + path.id = node.id; + } + + var className = node.className.trim(); + + if (className) { + path.className = className; + } + + return path; +}; + +var getPath = function getPath(node, root) { + var paths = []; + + while (node && node !== root) { + if (isElemNode(node)) { + paths.unshift(getNodeInfo(node)); + } + + node = node.parentNode; + } + + return paths; +}; +/** + * Find next, previous TD or TH element by given TE element + * @param {HTMLElement} node TD element + * @param {string} direction 'next' or 'previous' + * @returns {HTMLElement|null} + * @ignore + */ + + +var getTableCellByDirection = function getTableCellByDirection(node, direction) { + var targetElement = null; + + if (!tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(direction) && (direction === 'next' || direction === 'previous')) { + if (direction === 'next') { + targetElement = node.nextElementSibling; + } else { + targetElement = node.previousElementSibling; + } + } + + return targetElement; +}; +/** + * Find sibling TR's TD element by given TD and direction + * @param {HTMLElement} node TD element + * @param {string} direction Boolean value for find first TD in next line + * @param {boolean} [needEdgeCell=false] Boolean value for find first TD in next line + * @returns {HTMLElement|null} + * @ignore + */ + + +var getSiblingRowCellByDirection = function getSiblingRowCellByDirection(node, direction, needEdgeCell) { + var tableCellElement = null; + var index, targetRowElement, currentContainer, siblingContainer, isSiblingContainerExists; + + if (!tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(direction) && (direction === 'next' || direction === 'previous')) { + if (node) { + if (direction === 'next') { + targetRowElement = node.parentNode && node.parentNode.nextSibling; + currentContainer = parents(node, 'thead'); + siblingContainer = currentContainer[0] && currentContainer[0].nextSibling; + isSiblingContainerExists = siblingContainer && getNodeName(siblingContainer) === 'TBODY'; + index = 0; + } else { + targetRowElement = node.parentNode && node.parentNode.previousSibling; + currentContainer = parents(node, 'tbody'); + siblingContainer = currentContainer[0] && currentContainer[0].previousSibling; + isSiblingContainerExists = siblingContainer && getNodeName(siblingContainer) === 'THEAD'; + index = node.parentNode.childNodes.length - 1; + } + + if (tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(needEdgeCell) || !needEdgeCell) { + index = getNodeOffsetOfParent(node); + } + + if (targetRowElement) { + tableCellElement = children(targetRowElement, 'td,th')[index]; + } else if (currentContainer[0] && isSiblingContainerExists) { + tableCellElement = findAll(siblingContainer, 'td,th')[index]; + } + } + } + + return tableCellElement; +}; +/** + * Check that the inline node is supported by markdown + * @param {Node} node TD element + * @returns {boolean} + * @ignore + */ + + +var isMDSupportInlineNode = function isMDSupportInlineNode(node) { + return /^(A|B|BR|CODE|DEL|EM|I|IMG|S|SPAN|STRONG)$/gi.test(node.nodeName); +}; +/** + * Check that node is styled node. + * Styled node is a node that has text and decorates text. + * @param {Node} node TD element + * @returns {boolean} + * @ignore + */ + + +var isStyledNode = function isStyledNode(node) { + return /^(A|ABBR|ACRONYM|B|BDI|BDO|BIG|CITE|CODE|DEL|DFN|EM|I|INS|KBD|MARK|Q|S|SAMP|SMALL|SPAN|STRONG|SUB|SUP|U|VAR)$/gi.test(node.nodeName); +}; +/** + * remove node from 'start' node to 'end-1' node inside parent + * if 'end' node is null, remove all child nodes after 'start' node. + * @param {Node} parentNode - parent node + * @param {Node} start - start node to remove + * @param {Node} end - end node to remove + * @ignore + */ + + +var removeChildFromStartToEndNode = function removeChildFromStartToEndNode(parentNode, start, end) { + var child = start; + + if (!child || parentNode !== child.parentNode) { + return; + } + + while (child !== end) { + var nextNode = child.nextSibling; + parentNode.removeChild(child); + child = nextNode; + } +}; +/** + * remove nodes along the direction from the node to reach targetParent node + * @param {Node} targetParent - stop removing when reach target parent node + * @param {Node} node - start node + * @param {boolean} isForward - direction + * @ignore + */ + + +var removeNodesByDirection = function removeNodesByDirection(targetParent, node, isForward) { + var parentNode = node; + + while (parentNode !== targetParent) { + var nextParent = parentNode.parentNode; + var _parentNode = parentNode, + nextSibling = _parentNode.nextSibling, + previousSibling = _parentNode.previousSibling; + + if (!isForward && nextSibling) { + removeChildFromStartToEndNode(nextParent, nextSibling, null); + } else if (isForward && previousSibling) { + removeChildFromStartToEndNode(nextParent, nextParent.childNodes[0], parentNode); + } + + parentNode = nextParent; + } +}; + +var getLeafNode = function getLeafNode(node) { + var result = node; + + while (result.childNodes && result.childNodes.length) { + var _result = result, + nextLeaf = _result.firstChild; // When inline tag have empty text node with other childnodes, ignore empty text node. + + if (isTextNode(nextLeaf) && !getTextLength(nextLeaf)) { + result = nextLeaf.nextSibling || nextLeaf; + } else { + result = nextLeaf; + } + } + + return result; +}; +/** + * check if a coordinates is inside a button box + * @param {object} style - computed style of task box + * @param {number} offsetX - event x offset + * @param {number} offsetY - event y offset + * @returns {boolean} + * @ignore + */ + + +var isInsideButtonBox = function isInsideButtonBox(style, offsetX, offsetY) { + var rect = { + left: parseInt(style.left, 10), + top: parseInt(style.top, 10), + width: parseInt(style.width, 10), + height: parseInt(style.height, 10) + }; + return offsetX >= rect.left && offsetX <= rect.left + rect.width && offsetY >= rect.top && offsetY <= rect.top + rect.height; +}; +/** + * Check whether node is OL or UL + * @param {node} node - node + * @returns {boolean} - whether node is OL or UL + * @ignore + */ + + +var isListNode = function isListNode(node) { + if (!node) { + return false; + } + + return node.nodeName === 'UL' || node.nodeName === 'OL'; +}; +/** + * Check whether node is first list item + * @param {node} node - node + * @returns {boolean} whether node is first list item + * @ignore + */ + + +var isFirstListItem = function isFirstListItem(node) { + var nodeName = node.nodeName, + parentNode = node.parentNode; + return nodeName === 'LI' && node === parentNode.firstChild; +}; +/** + * Check whether node is first level list item + * @param {node} node - node + * @returns {boolean} whether node is first level list item + * @ignore + */ + + +var isFirstLevelListItem = function isFirstLevelListItem(node) { + var nodeName = node.nodeName, + listNode = node.parentNode; + var listParentNode = listNode.parentNode; + return nodeName === 'LI' && !isListNode(listParentNode); +}; +/** + * Merge node to target node and detach node + * @param {node} node - node + * @param {node} targetNode - target node + * @ignore + */ + + +var mergeNode = function mergeNode(node, targetNode) { + if (node.hasChildNodes()) { + tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(node.childNodes).forEach(function () { + targetNode.appendChild(node.firstChild); + }); + targetNode.normalize(); + } + + if (node.parentNode) { + node.parentNode.removeChild(node); + } +}; +/** + * Create hr that is not contenteditable + * @returns {node} hr is wraped div + * @ignore + */ + + +var createHorizontalRule = function createHorizontalRule() { + var div = document.createElement('div'); + var hr = document.createElement('hr'); + div.setAttribute('contenteditable', false); + hr.setAttribute('contenteditable', false); + div.appendChild(hr); + return div; +}; +/** + * Create Empty Line + * @returns {node}

      + * @private + */ + + +var createEmptyLine = function createEmptyLine() { + var div = document.createElement('div'); + div.appendChild(document.createElement('br')); + return div; +}; +/** + * Find same tagName child node and change wrapping order. + * For example, if below node need to optimize 'B' tag. + * test + * should be changed tag's order. + * test + * @param {node} node + * @param {string} tagName + * @returns {node} + * @private + */ + + +var changeTagOrder = function changeTagOrder(node, tagName) { + if (node.nodeName !== 'SPAN') { + var parentNode = node.parentNode; + var tempNode = node; + + while (tempNode.childNodes && tempNode.childNodes.length === 1 && !isTextNode(tempNode.firstChild)) { + tempNode = tempNode.firstChild; + + if (tempNode.nodeName === 'SPAN') { + break; + } + + if (tempNode.nodeName === tagName) { + var wrapper = document.createElement(tagName); + mergeNode(tempNode, tempNode.parentNode); + parentNode.replaceChild(wrapper, node); + wrapper.appendChild(node); + return wrapper; + } + } + } + + return node; +}; +/** + * Find same tagName nodes and merge from startNode to endNode. + * @param {node} startNode + * @param {node} endNode + * @param {string} tagName + * @returns {node} + * @private + */ + + +var mergeSameNodes = function mergeSameNodes(startNode, endNode, tagName) { + var startBlockNode = changeTagOrder(startNode, tagName); + + if (startBlockNode.nodeName === tagName) { + var endBlockNode = changeTagOrder(endNode, tagName); + var mergeTargetNode = startBlockNode; + var nextNode = startBlockNode.nextSibling; + + while (nextNode) { + var tempNext = nextNode.nextSibling; + nextNode = changeTagOrder(nextNode, tagName); + + if (nextNode.nodeName === tagName) { + // eslint-disable-next-line max-depth + if (mergeTargetNode) { + mergeNode(nextNode, mergeTargetNode); + } else { + mergeTargetNode = nextNode; + } + } else { + mergeTargetNode = null; + } + + if (nextNode === endBlockNode) { + break; + } + + nextNode = tempNext; + } + } +}; +/** + * Find same tagName nodes in range and merge nodes. + * For example range is like this + * AAABBB + * nodes is changed below + * AAABBB + * @param {range} range + * @param {string} tagName + * @private + */ + + +var optimizeRange = function optimizeRange(range, tagName) { + var collapsed = range.collapsed, + commonAncestorContainer = range.commonAncestorContainer, + startContainer = range.startContainer, + endContainer = range.endContainer; + + if (!collapsed) { + var optimizedNode = null; + + if (startContainer !== endContainer) { + var startNode = getParentUntil(startContainer, commonAncestorContainer); + var endNode = getParentUntil(endContainer, commonAncestorContainer); + + if (startNode && endNode) { + mergeSameNodes(startNode, endNode, tagName); + } + + optimizedNode = commonAncestorContainer; + } else if (isTextNode(startContainer)) { + optimizedNode = startContainer.parentNode; + } + + if (optimizedNode && optimizedNode.nodeName === tagName) { + var _optimizedNode = optimizedNode, + previousSibling = _optimizedNode.previousSibling; + var tempNode; + + if (previousSibling) { + tempNode = changeTagOrder(previousSibling); + + if (tempNode.nodeName === tagName) { + mergeNode(optimizedNode, tempNode); + } + } + + var _optimizedNode2 = optimizedNode, + nextSibling = _optimizedNode2.nextSibling; + + if (nextSibling) { + tempNode = changeTagOrder(nextSibling); + + if (tempNode.nodeName === tagName) { + mergeNode(tempNode, optimizedNode); + } + } + } + } +}; +/** + * Gets all text node from root element. + * @param {HTMLElement} root Root element + * @returns {Array} list of text nodes + * @ignore + */ + + +var getAllTextNode = function getAllTextNode(root) { + var walker = document.createTreeWalker(root, 4, null, false); + var result = []; + + while (walker.nextNode()) { + var node = walker.currentNode; + + if (isTextNode(node)) { + result.push(node); + } + } + + return result; +}; +/** + * Check whether the node is 'TD' or 'TH' + * @param {HTMLElement} node - the target node + * @returns {boolean} - whether the node is 'TD' or 'TH' + * @ignore + */ + + +var isCellNode = function isCellNode(node) { + if (!node) { + return false; + } + + return node.nodeName === 'TD' || node.nodeName === 'TH'; +}; +/** + * Get the last node on the target node by the condition + * @param {HTMLElement} node - the target node + * @returns {function} - the condition to find the node + * @ignore + */ + + +var getLastNodeBy = function getLastNodeBy(node, condition) { + var lastNode = node && node.lastChild; + + while (lastNode && condition(lastNode)) { + lastNode = lastNode.lastChild; + } + + return lastNode; +}; +/** + * Get the parent node on the target node by the condition + * @param {HTMLElement} node - the target node + * @returns {function} - the condition to find the node + * @ignore + */ + + +var getParentNodeBy = function getParentNodeBy(node, condition) { + while (node && condition(node.parentNode, node)) { + node = node.parentNode; + } + + return node; +}; +/** + * Get the sibling node on the target node by the condition + * @param {HTMLElement} node - the target node + * @param {string} direction - the direction to find node ('previous', 'next') + * @returns {function} - the condition to find the node + * @ignore + */ + + +var getSiblingNodeBy = function getSiblingNodeBy(node, direction, condition) { + var directionKey = direction + "Sibling"; + + while (node && condition(node[directionKey], node)) { + node = node[directionKey]; + } + + return node; +}; +/** + * Create element with contents + * @param {string|Node} contents - contents to appended + * @param {HTMLElement} [target] - container element to append contents + * @returns {Node} created node + * @ignore + */ + + +function createElementWith(contents, target) { + var container = document.createElement('div'); + + if (tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default()(contents)) { + container.innerHTML = contents; + } else { + container.appendChild(contents); + } + + var firstChild = container.firstChild; + + if (target) { + target.appendChild(firstChild); + } + + return firstChild; +} +/** + * Find nodes matching by selector + * @param {HTMLElement} element - target element + * @param {string} selector - selector to find nodes + * @returns {Array.} found nodes + * @ignore + */ + + +function findAll(element, selector) { + var nodeList = tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(element.querySelectorAll(selector)); + + if (nodeList.length) { + return nodeList; + } + + return []; +} +/** + * Checks whether specific node is included in target node + * @param {HTMLElement} element - target to find + * @param {Node} containedNode - node to find + * @returns {boolean} whether node is contained or not + * @ignore + */ + + +function isContain(element, contained) { + return element !== contained && element.contains(contained); +} +/** + * Gets closest node matching by selector + * @param {Node} node - target node + * @param {string|Node} found - selector or element to find node + * @param {Node} [root] - root node + * @returns {?Node} - found node + * @ignore + */ + + +function closest(node, found, root) { + var condition; + root = root || document; + + if (tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default()(found)) { + condition = function condition(target) { + return tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default()(target, found); + }; + } else { + condition = function condition(target) { + return target === found; + }; + } + + while (node && node !== root) { + if (isElemNode(node) && condition(node)) { + return node; + } + + node = node.parentNode; + } + + return null; +} +/** + * Gets parent node matching by selector from target node + * @param {Node} node - target node + * @param {string} [selector] - selector to find + * @returns {Node} found node + * @ignore + */ + + +function parent(node, selector) { + var parentNode = node.parentNode; + + if (selector) { + return parentNode && tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default()(parentNode, selector) ? parentNode : null; + } + + return parentNode; +} +/** + * Gets ancestor nodes matching by selector from target node + * @param {Node} node - target node + * @param {string|Node} found - selector or node to find + * @returns {Array.} found nodes + * @ignore + */ + + +function parents(node, found) { + var result = []; + + while (node && node !== document) { + node = closest(node.parentNode, found); + + if (node) { + result.push(node); + } + } + + return result; +} +/** + * Gets ancestor nodes until matching by selector from target node + * @param {Node} node - target node + * @param {string} selector - selector to find + * @param {Array.} found nodes + * @ignore + */ + + +function parentsUntil(node, selector) { + var result = []; + + while (node.parentNode && !tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default()(node.parentNode, selector)) { + node = node.parentNode; + + if (node) { + result.push(node); + } + } + + return result; +} +/** + * Gets child nodes matching by selector from target node + * @param {Node} node - target node + * @param {string} selector - selector to find + * @returns {Array.} found nodes + * @ignore + */ + + +function children(node, selector) { + var foundChildren; + + if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { + foundChildren = node.childNodes; + } else { + foundChildren = node.children; + } + + return tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(foundChildren).filter(function (child) { + return tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default()(child, selector); + }); +} +/** + * Appends node(s) on target node + * @param {Node} node - target node + * @param {string|Node} appended - html string or node to append + * @ignore + */ + + +function append(node, appended) { + if (tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default()(appended)) { + node.insertAdjacentHTML('beforeEnd', appended); + } else { + appended = appended.length ? tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(appended) : [appended]; + + for (var i = 0, len = appended.length; i < len; i += 1) { + node.appendChild(appended[i]); + } + } +} +/** + * Prepends node(s) on target node + * @param {Node} node - target node + * @param {string|Node} appended - html string or node to append + * @ignore + */ + + +function prepend(node, appended) { + if (tui_code_snippet_type_isString__WEBPACK_IMPORTED_MODULE_2___default()(appended)) { + node.insertAdjacentHTML('afterBegin', appended); + } else { + appended = appended.length ? tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(appended) : [appended]; + + for (var i = appended.length - 1, len = 0; i >= len; i -= 1) { + node.insertBefore(appended[i], node.firstChild); + } + } +} +/** + * Inserts new node in front of target node + * @param {Node} insertedNode - node to insert + * @param {Node} node - target node + * @ignore + */ + + +function insertBefore(insertedNode, node) { + var parentNode = node.parentNode; + + if (parentNode) { + parentNode.insertBefore(insertedNode, node); + } +} +/** + * Inserts new node after target node + * @param {Node} insertedNode - node to insert + * @param {Node} node - target node + * @ignore + */ + + +function insertAfter(insertedNode, node) { + var parentNode = node.parentNode; + + if (parentNode) { + parentNode.insertBefore(insertedNode, node.nextSibling); + } +} +/** + * Replaces target node(s) with html + * @param {Node} nodeList - target node(s) to replace + * @param {string} html - replaced html + * @ignore + */ + + +function replaceWith(nodeList, html) { + nodeList = nodeList.length ? tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(nodeList) : [nodeList]; + nodeList.forEach(function (node) { + node.insertAdjacentHTML('afterEnd', html); + node.parentNode.removeChild(node); + }); +} +/** + * Adds parent element to target node(s) + * @param {Node|Array.} nodeList - target node(s) + * @param {string} nodeName - node name to change parent element + * @ignore + */ + + +function wrap(nodeList, nodeName) { + nodeList = nodeList.length ? tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(nodeList) : [nodeList]; + nodeList.forEach(function (node) { + var wrapper = document.createElement(nodeName); + node.parentNode.insertBefore(wrapper, node); + wrapper.appendChild(node); + }); +} +/** + * Adds child element to target node(s) + * @param {Node|Array.} nodeList - target node(s) + * @param {string} nodeName - node name to change child element + * @ignore + */ + + +function wrapInner(nodeList, nodeName) { + nodeList = nodeList.length ? tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(nodeList) : [nodeList]; + nodeList.forEach(function (node) { + var wrapper = document.createElement(nodeName); + node.appendChild(wrapper); + + while (node.firstChild !== wrapper) { + wrapper.appendChild(node.firstChild); + } + }); +} +/** + * Removes target element and insert children at the same position + * @param {Node} node - parent node + * @returns {Array.} unwrapped nodes + * @ignore + */ + + +function unwrap(node) { + var result = []; + + while (node.firstChild) { + result.push(node.firstChild); + node.parentNode.insertBefore(node.firstChild, node); + } + + remove(node); + return result; +} +/** + * Removes target node from parent node + * @param {Node} node - target node + * @ignore + */ + + +function remove(node) { + if (node.parentNode) { + node.parentNode.removeChild(node); + } +} +/** + * Removes all children of target node + * @param {Node} node - target node + * @ignore + */ + + +function empty(node) { + while (node.firstChild) { + node.removeChild(node.firstChild); + } +} +/** + * Sets offset value of target element + * @param {HTMLElement} element - target element + * @returns {Object.} offset values + * @ignore + */ + + +function setOffset(element, offset) { + var _element$parentNode$g = element.parentNode.getBoundingClientRect(), + top = _element$parentNode$g.top, + left = _element$parentNode$g.left; + + tui_code_snippet_domUtil_css__WEBPACK_IMPORTED_MODULE_3___default()(element, { + top: offset.top - top - document.body.scrollTop + "px" + }); + tui_code_snippet_domUtil_css__WEBPACK_IMPORTED_MODULE_3___default()(element, { + left: offset.left - left - document.body.scrollLeft + "px" + }); +} +/** + * Gets offset value of target element + * @param {HTMLElement} element - target element + * @param {string} [selector] - selector to stop finding node + * @returns {Object.} offset values + * @ignore + */ + + +function getOffset(element, selector) { + if (selector === void 0) { + selector = 'document'; + } + + var top = 0; + var left = 0; + + do { + top += element.offsetTop || 0; + left += element.offsetLeft || 0; + element = element.offsetParent; + } while (element && !tui_code_snippet_domUtil_matches__WEBPACK_IMPORTED_MODULE_7___default()(element, selector)); + + return { + top: top, + left: left + }; +} +/** + * Gets outer width value of target element + * @param {HTMLElement} element - target element + * @param {boolean} includedMargin - whether to include margir or not + * @returns {number} outer width value + * @ignore + */ + + +function getOuterWidth(element, includedMargin) { + var widthValue = element.offsetWidth; + + if (includedMargin) { + var _getComputedStyle = getComputedStyle(element), + marginLeft = _getComputedStyle.marginLeft, + marginRight = _getComputedStyle.marginRight; + + widthValue += parseInt(marginLeft, 10) + parseInt(marginRight, 10); + } + + return widthValue; +} +/** + * Gets outer height value of target element + * @param {HTMLElement} element - target element + * @param {boolean} includedMargin - whether to include margir or not + * @returns {number} outer height value + * @ignore + */ + + +function getOuterHeight(element, includedMargin) { + var heightValue = element.offsetHeight; + + if (includedMargin) { + var _getComputedStyle2 = getComputedStyle(element), + marginTop = _getComputedStyle2.marginTop, + marginBottom = _getComputedStyle2.marginBottom; + + heightValue += parseInt(marginTop, 10) + parseInt(marginBottom, 10); + } + + return heightValue; +} +/** + * Toggles class name of target element + * @param {HTMLElement} element - target element + * @param {string} className - class name to toggle + * @param {boolean} [state] - whether to toggle or not by condition + * @ignore + */ + + +var toggleClass = function toggleClass(element, className, state) { + if (tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(state)) { + state = !tui_code_snippet_domUtil_hasClass__WEBPACK_IMPORTED_MODULE_6___default()(element, className); + } + + var toggleFn = state ? tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_4___default.a : tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_5___default.a; + toggleFn(element, className); +}; +/** + * Finalize html result + * @param {HTMLElement} html root element + * @param {boolean} needHtmlText pass true if need html text + * @returns {string|DocumentFragment} result + * @ignore + */ + + +function finalizeHtml(html, needHtmlText) { + var result; + + if (needHtmlText) { + result = html.innerHTML; + } else { + var frag = document.createDocumentFragment(); + var childNodes = tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(html.childNodes); + var length = childNodes.length; + + for (var i = 0; i < length; i += 1) { + frag.appendChild(childNodes[i]); + } + + result = frag; + } + + return result; +} +/** + * Get fragment replaced by newline to br tag + * @param {string} text original text + * @returns {DocumentFragment} fragment + * @ignore + */ + + +function getFragmentReplacedByNewlineToBr(text) { + var fragment = document.createDocumentFragment(); + var texts = text.split('\n'); + texts.forEach(function (plainText, index) { + var textNode = document.createTextNode(plainText); + fragment.appendChild(textNode); + + if (index < texts.length - 1) { + fragment.appendChild(document.createElement('br')); + } + }); + return fragment; +} + +/* harmony default export */ __webpack_exports__["a"] = ({ + getNodeName: getNodeName, + isTextNode: isTextNode, + isElemNode: isElemNode, + isBlockNode: isBlockNode, + getTextLength: getTextLength, + getOffsetLength: getOffsetLength, + getPrevOffsetNodeUntil: getPrevOffsetNodeUntil, + getNodeOffsetOfParent: getNodeOffsetOfParent, + getChildNodeByOffset: getChildNodeByOffset, + getNodeWithDirectionUntil: getNodeWithDirectionUntil, + containsNode: containsNode, + getTopPrevNodeUnder: getTopPrevNodeUnder, + getTopNextNodeUnder: getTopNextNodeUnder, + getParentUntilBy: getParentUntilBy, + getParentUntil: getParentUntil, + getTopBlockNode: getTopBlockNode, + getPrevTextNode: getPrevTextNode, + findOffsetNode: findOffsetNode, + getPath: getPath, + getNodeInfo: getNodeInfo, + getTableCellByDirection: getTableCellByDirection, + getSiblingRowCellByDirection: getSiblingRowCellByDirection, + isMDSupportInlineNode: isMDSupportInlineNode, + isStyledNode: isStyledNode, + removeChildFromStartToEndNode: removeChildFromStartToEndNode, + removeNodesByDirection: removeNodesByDirection, + getLeafNode: getLeafNode, + isInsideButtonBox: isInsideButtonBox, + isListNode: isListNode, + isFirstListItem: isFirstListItem, + isFirstLevelListItem: isFirstLevelListItem, + mergeNode: mergeNode, + createHorizontalRule: createHorizontalRule, + createEmptyLine: createEmptyLine, + changeTagOrder: changeTagOrder, + mergeSameNodes: mergeSameNodes, + optimizeRange: optimizeRange, + getAllTextNode: getAllTextNode, + isCellNode: isCellNode, + getLastNodeBy: getLastNodeBy, + getParentNodeBy: getParentNodeBy, + getSiblingNodeBy: getSiblingNodeBy, + createElementWith: createElementWith, + findAll: findAll, + isContain: isContain, + closest: closest, + parent: parent, + parents: parents, + parentsUntil: parentsUntil, + children: children, + append: append, + prepend: prepend, + insertBefore: insertBefore, + insertAfter: insertAfter, + replaceWith: replaceWith, + wrap: wrap, + wrapInner: wrapInner, + unwrap: unwrap, + remove: remove, + empty: empty, + setOffset: setOffset, + getOffset: getOffset, + getOuterWidth: getOuterWidth, + getOuterHeight: getOuterHeight, + toggleClass: toggleClass, + finalizeHtml: finalizeHtml, + getFragmentReplacedByNewlineToBr: getFragmentReplacedByNewlineToBr +}); + +/***/ }), +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/object/extend.js +var extend = __webpack_require__(7); +var extend_default = /*#__PURE__*/__webpack_require__.n(extend); + +// CONCATENATED MODULE: ./src/js/command.js +/** + * @fileoverview Implements Command + * @author NHN FE Development Lab + */ + +/** + * Class Command + * @param {string} name Command name + * @param {number} type Command type (Command.TYPE) + * @param {Array.} [keyMap] keyMap + * @ignore + */ + +var Command = /*#__PURE__*/function () { + function Command(name, type, keyMap) { + this.name = name; + this.type = type; + + if (keyMap) { + this.setKeyMap(keyMap); + } + } + /** + * returns Name of command + * @returns {string} Command Name + */ + + + var _proto = Command.prototype; + + _proto.getName = function getName() { + return this.name; + } + /** + * returns Type of command + * @returns {number} Command Command type number + */ + ; + + _proto.getType = function getType() { + return this.type; + } + /** + * returns whether Command Type is Markdown or not + * @returns {boolean} result + */ + ; + + _proto.isMDType = function isMDType() { + return this.type === Command.TYPE.MD; + } + /** + * returns whether Command Type is Wysiwyg or not + * @returns {boolean} result + */ + ; + + _proto.isWWType = function isWWType() { + return this.type === Command.TYPE.WW; + } + /** + * returns whether Command Type is Global or not + * @returns {boolean} result + */ + ; + + _proto.isGlobalType = function isGlobalType() { + return this.type === Command.TYPE.GB; + } + /** + * Set keymap value for each os + * @param {string} win Windows Key(and etc) + * @param {string} mac Mac osx key + */ + ; + + _proto.setKeyMap = function setKeyMap(win, mac) { + this.keyMap = [win, mac]; + }; + + return Command; +}(); +/** + * Command factory method + * @param {string} typeStr Editor type name + * @param {object} props Property + * @param {string} props.name Command name + * @param {number} props.type Command type number + * @returns {Command} + * @static + */ + + +Command.factory = function (typeStr, props) { + var type; + + if (typeStr === 'markdown') { + type = Command.TYPE.MD; + } else if (typeStr === 'wysiwyg') { + type = Command.TYPE.WW; + } else if (typeStr === 'global') { + type = Command.TYPE.GB; + } + + var command = new Command(props.name, type); + extend_default()(command, props); + return command; +}; +/** + * Command Type Constant + * markdown : 0 + * wysiwyg : 1 + * global : 2 + * @type {object} + * @private + */ + + +Command.TYPE = { + MD: 0, + WW: 1, + GB: 2 +}; +/* harmony default export */ var js_command = (Command); +// EXTERNAL MODULE: ./src/js/utils/common.js +var common = __webpack_require__(12); + +// EXTERNAL MODULE: ./src/js/utils/map.js +var map = __webpack_require__(23); + +// CONCATENATED MODULE: ./src/js/commandManager.js +/** + * @fileoverview Implements CommandManager + * @author NHN FE Development Lab + */ + + + + +var KEYMAP_OS_INDEX = common["b" /* isMac */] ? 1 : 0; +/** + * Class CommandManager + * @param {ToastUIEditor} base nedInstance + * @param {object} [options={}] - option object + * @param {boolean} [options.useCommandShortcut=true] - execute command with keyMap + * @ignore + */ + +var commandManager_CommandManager = /*#__PURE__*/function () { + function CommandManager(base, options) { + if (options === void 0) { + options = {}; + } + + this._command = new map["a" /* default */](); + this._mdCommand = new map["a" /* default */](); + this._wwCommand = new map["a" /* default */](); + this._options = extend_default()({ + useCommandShortcut: true + }, options); + this.base = base; + this.keyMapCommand = {}; + + this._initEvent(); + } + /** + * You can change command before command addition by addCommandBefore event. + * @param {object} command - command + * @returns {object} + * @private + */ + + + var _proto = CommandManager.prototype; + + _proto._addCommandBefore = function _addCommandBefore(command) { + var commandWrapper = { + command: command + }; + this.base.eventManager.emit('addCommandBefore', commandWrapper); + return commandWrapper.command || command; + } + /** + * Add command + * @param {Command} command Command instance + * @returns {Command} Command + */ + ; + + _proto.addCommand = function addCommand(command) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + if (args.length) { + command = CommandManager.command.apply(CommandManager, [command].concat(args)); + } + + command = this._addCommandBefore(command); + var name = command.getName(); + var commandBase; + + if (command.isMDType()) { + commandBase = this._mdCommand; + } else if (command.isWWType()) { + commandBase = this._wwCommand; + } else if (command.isGlobalType()) { + commandBase = this._command; + } + + commandBase.set(name, command); + + if (command.keyMap) { + this.keyMapCommand[command.keyMap[KEYMAP_OS_INDEX]] = name; + } + + return command; + } + /** + * _initEvent + * Bind event handler to eventManager + * @private + */ + ; + + _proto._initEvent = function _initEvent() { + var _this = this; + + this.base.eventManager.listen('command', function () { + _this.exec.apply(_this, arguments); + }); + this.base.eventManager.listen('keyMap', function (ev) { + if (!_this._options.useCommandShortcut) { + return; + } + + var command = _this.keyMapCommand[ev.keyMap]; + + if (command) { + ev.data.preventDefault(); + + _this.exec(command); + } + }); + } + /** + * Execute command + * @param {String} name Command name + * @param {*} ...args Command argument + * @returns {*} + */ + ; + + _proto.exec = function exec(name) { + var commandToRun, result; + var context = this.base; + commandToRun = this._command.get(name); + + if (!commandToRun) { + if (this.base.isMarkdownMode()) { + commandToRun = this._mdCommand.get(name); + context = this.base.mdEditor; + } else { + commandToRun = this._wwCommand.get(name); + context = this.base.wwEditor; + } + } + + if (commandToRun) { + var _commandToRun; + + for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { + args[_key2 - 1] = arguments[_key2]; + } + + args.unshift(context); + result = (_commandToRun = commandToRun).exec.apply(_commandToRun, args); + } + + return result; + }; + + return CommandManager; +}(); +/** + * Create command by given editor type and property object + * @param {string} type Command type + * @param {{name: string, keyMap: Array}} props Property + * @returns {*} + * @static + */ + + +commandManager_CommandManager.command = function (type, props) { + var command = js_command.factory(type, props.name, props.keyMap); + extend_default()(command, props); + return command; +}; + +/* harmony default export */ var commandManager = __webpack_exports__["a"] = (commandManager_CommandManager); + +/***/ }), +/* 2 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export hasImageOrCodeBlockNode */ +/* unused harmony export hasSameLineParent */ +/* unused harmony export hasSpecificTypeAncestor */ +/* unused harmony export isEmptyLineNode */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return getMdStartLine; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return getMdEndLine; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return getMdStartCh; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return getMdEndCh; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "j", function() { return isMultiLineNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return isHtmlNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "k", function() { return isStyledTextNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return isListItemNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "l", function() { return isTableCellNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return isInlineNode; }); +/* unused harmony export getLastLeafNode */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return findClosestNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "n", function() { return traverseParentNodes; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return addChPos; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "m", function() { return setChPos; }); +/* harmony import */ var _common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); + +function hasImageOrCodeBlockNode(mdNode) { + while (mdNode) { + if (Object(_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(['image', 'codeBlock'], mdNode.type)) { + return true; + } + + mdNode = mdNode.firstChild; + } + + return false; +} +function hasSameLineParent(mdNode) { + return mdNode.parent && mdNode.parent.type !== 'document' && mdNode.parent.sourcepos[0][0] === mdNode.sourcepos[0][0]; +} +function hasSpecificTypeAncestor(mdNode) { + for (var _len = arguments.length, types = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + types[_key - 1] = arguments[_key]; + } + + while (mdNode.parent && mdNode.parent.type !== 'document') { + if (Object(_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(types, mdNode.parent.type)) { + return true; + } + + mdNode = mdNode.parent; + } + + return false; +} +function isEmptyLineNode(text, mdNode) { + return !text.trim() && !hasImageOrCodeBlockNode(mdNode); +} +function getMdStartLine(mdNode) { + return mdNode.sourcepos[0][0]; +} +function getMdEndLine(mdNode) { + return mdNode.sourcepos[1][0]; +} +function getMdStartCh(mdNode) { + return mdNode.sourcepos[0][1]; +} +function getMdEndCh(mdNode) { + return mdNode.sourcepos[1][1]; +} +function isMultiLineNode(mdNode) { + var type = mdNode.type; + return type === 'codeBlock' || type === 'paragraph'; +} +function isHtmlNode(mdNode) { + var type = mdNode.type; + return type === 'htmlBlock' || type === 'htmlInline'; +} +function isStyledTextNode(mdNode) { + var type = mdNode.type; + return type === 'strike' || type === 'strong' || type === 'emph'; +} +function isListItemNode(mdNode) { + return mdNode.type === 'item'; +} +function isTableCellNode(mdNode) { + var type = mdNode.type; + return type === 'tableCell' || type === 'tableDelimCell'; +} +function isInlineNode(mdNode) { + switch (mdNode.type) { + case 'code': + case 'text': + case 'emph': + case 'strong': + case 'strike': + case 'link': + case 'image': + case 'htmlInline': + case 'linebreak': + case 'softbreak': + return true; + + default: + return false; + } +} +function getLastLeafNode(mdNode) { + while (mdNode.lastChild) { + mdNode = mdNode.lastChild; + } + + return mdNode; +} +function findClosestNode(mdNode, condition, includeSelf) { + if (includeSelf === void 0) { + includeSelf = true; + } + + mdNode = includeSelf ? mdNode : mdNode.parent; + + while (mdNode && mdNode.type !== 'document') { + if (condition(mdNode)) { + return mdNode; + } + + mdNode = mdNode.parent; + } + + return null; +} +function traverseParentNodes(mdNode, iteratee, includeSelf) { + if (includeSelf === void 0) { + includeSelf = true; + } + + mdNode = includeSelf ? mdNode : mdNode.parent; + + while (mdNode && mdNode.type !== 'document') { + iteratee(mdNode); + mdNode = mdNode.parent; + } +} +function addChPos(originPos, addedCh) { + return { + line: originPos.line, + ch: originPos.ch + addedCh + }; +} +function setChPos(originPos, newCh) { + return { + line: originPos.line, + ch: newCh + }; +} + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Transform the Array-like object to Array. + * @author NHN FE Development Lab + */ + + + +var forEachArray = __webpack_require__(21); + +/** + * Transform the Array-like object to Array. + * In low IE (below 8), Array.prototype.slice.call is not perfect. So, try-catch statement is used. + * @param {*} arrayLike Array-like object + * @returns {Array} Array + * @memberof module:collection + * @example + * var toArray = require('tui-code-snippet/collection/toArray'); // node, commonjs + * + * var arrayLike = { + * 0: 'one', + * 1: 'two', + * 2: 'three', + * 3: 'four', + * length: 4 + * }; + * var result = toArray(arrayLike); + * + * alert(result instanceof Array); // true + * alert(result); // one,two,three,four + */ +function toArray(arrayLike) { + var arr; + try { + arr = Array.prototype.slice.call(arrayLike); + } catch (e) { + arr = []; + forEachArray(arrayLike, function(value) { + arr.push(value); + }); + } + + return arr; +} + +module.exports = toArray; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Setting element style + * @author NHN FE Development Lab + */ + + + +var isString = __webpack_require__(9); +var forEach = __webpack_require__(26); + +/** + * Setting element style + * @param {(HTMLElement|SVGElement)} element - element to setting style + * @param {(string|object)} key - style prop name or {prop: value} pair object + * @param {string} [value] - style value + * @memberof module:domUtil + */ +function css(element, key, value) { + var style = element.style; + + if (isString(key)) { + style[key] = value; + + return; + } + + forEach(key, function(v, k) { + style[k] = v; + }); +} + +module.exports = css; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Add css class to element + * @author NHN FE Development Lab + */ + + + +var forEach = __webpack_require__(26); +var inArray = __webpack_require__(14); +var getClass = __webpack_require__(33); +var setClassName = __webpack_require__(39); + +/** + * domUtil module + * @module domUtil + */ + +/** + * Add css class to element + * @param {(HTMLElement|SVGElement)} element - target element + * @param {...string} cssClass - css classes to add + * @memberof module:domUtil + */ +function addClass(element) { + var cssClass = Array.prototype.slice.call(arguments, 1); + var classList = element.classList; + var newClass = []; + var origin; + + if (classList) { + forEach(cssClass, function(name) { + element.classList.add(name); + }); + + return; + } + + origin = getClass(element); + + if (origin) { + cssClass = [].concat(origin.split(/\s+/), cssClass); + } + + forEach(cssClass, function(cls) { + if (inArray(cls, newClass) < 0) { + newClass.push(cls); + } + }); + + setClassName(element, newClass); +} + +module.exports = addClass; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Remove css class from element + * @author NHN FE Development Lab + */ + + + +var forEachArray = __webpack_require__(21); +var inArray = __webpack_require__(14); +var getClass = __webpack_require__(33); +var setClassName = __webpack_require__(39); + +/** + * Remove css class from element + * @param {(HTMLElement|SVGElement)} element - target element + * @param {...string} cssClass - css classes to remove + * @memberof module:domUtil + */ +function removeClass(element) { + var cssClass = Array.prototype.slice.call(arguments, 1); + var classList = element.classList; + var origin, newClass; + + if (classList) { + forEachArray(cssClass, function(name) { + classList.remove(name); + }); + + return; + } + + origin = getClass(element).split(/\s+/); + newClass = []; + forEachArray(origin, function(name) { + if (inArray(name, cssClass) < 0) { + newClass.push(name); + } + }); + + setClassName(element, newClass); +} + +module.exports = removeClass; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Extend the target object from other objects. + * @author NHN FE Development Lab + */ + + + +/** + * @module object + */ + +/** + * Extend the target object from other objects. + * @param {object} target - Object that will be extended + * @param {...object} objects - Objects as sources + * @returns {object} Extended object + * @memberof module:object + */ +function extend(target, objects) { // eslint-disable-line no-unused-vars + var hasOwnProp = Object.prototype.hasOwnProperty; + var source, prop, i, len; + + for (i = 1, len = arguments.length; i < len; i += 1) { + source = arguments[i]; + for (prop in source) { + if (hasOwnProp.call(source, prop)) { + target[prop] = source[prop]; + } + } + } + + return target; +} + +module.exports = extend; + + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is undefined or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is undefined or not. + * If the given variable is undefined, returns true. + * @param {*} obj - Target for checking + * @returns {boolean} Is undefined? + * @memberof module:type + */ +function isUndefined(obj) { + return obj === undefined; // eslint-disable-line no-undefined +} + +module.exports = isUndefined; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is a string or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is a string or not. + * If the given variable is a string, return true. + * @param {*} obj - Target for checking + * @returns {boolean} Is string? + * @memberof module:type + */ +function isString(obj) { + return typeof obj === 'string' || obj instanceof String; +} + +module.exports = isString; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Execute the provided callback once for each property of object which actually exist. + * @author NHN FE Development Lab + */ + + + +/** + * Execute the provided callback once for each property of object which actually exist. + * If the callback function returns false, the loop will be stopped. + * Callback function(iteratee) is invoked with three arguments: + * 1) The value of the property + * 2) The name of the property + * 3) The object being traversed + * @param {Object} obj The object that will be traversed + * @param {function} iteratee Callback function + * @param {Object} [context] Context(this) of callback function + * @memberof module:collection + * @example + * var forEachOwnProperties = require('tui-code-snippet/collection/forEachOwnProperties'); // node, commonjs + * + * var sum = 0; + * + * forEachOwnProperties({a:1,b:2,c:3}, function(value){ + * sum += value; + * }); + * alert(sum); // 6 + */ +function forEachOwnProperties(obj, iteratee, context) { + var key; + + context = context || null; + + for (key in obj) { + if (obj.hasOwnProperty(key)) { + if (iteratee.call(context, obj[key], key, obj) === false) { + break; + } + } + } +} + +module.exports = forEachOwnProperties; + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview This module detects the kind of well-known browser and version. + * @author NHN FE Development Lab + */ + + + +/** + * Browser module + * @module browser + */ + +/** + * This object has an information that indicate the kind of browser. It can detect IE8 ~ IE11, Chrome, Firefox, Safari, and Edge. + * @memberof module:browser + * @example + * var browser = require('tui-code-snippet/browser/browser'); // node, commonjs + * + * browser.chrome === true; // chrome + * browser.firefox === true; // firefox + * browser.safari === true; // safari + * browser.msie === true; // IE + * browser.edge === true; // edge + * browser.others === true; // other browser + * browser.version; // browser version + */ +var browser = { + chrome: false, + firefox: false, + safari: false, + msie: false, + edge: false, + others: false, + version: 0 +}; + +if (typeof window !== 'undefined' && window.navigator) { + detectBrowser(); +} + +/** + * Detect the browser. + * @private + */ +function detectBrowser() { + var nav = window.navigator; + var appName = nav.appName.replace(/\s/g, '_'); + var userAgent = nav.userAgent; + + var rIE = /MSIE\s([0-9]+[.0-9]*)/; + var rIE11 = /Trident.*rv:11\./; + var rEdge = /Edge\/(\d+)\./; + var versionRegex = { + firefox: /Firefox\/(\d+)\./, + chrome: /Chrome\/(\d+)\./, + safari: /Version\/([\d.]+).*Safari\/(\d+)/ + }; + + var key, tmp; + + var detector = { + Microsoft_Internet_Explorer: function() { // eslint-disable-line camelcase + var detectedVersion = userAgent.match(rIE); + + if (detectedVersion) { // ie8 ~ ie10 + browser.msie = true; + browser.version = parseFloat(detectedVersion[1]); + } else { // no version information + browser.others = true; + } + }, + Netscape: function() { // eslint-disable-line complexity + var detected = false; + + if (rIE11.exec(userAgent)) { + browser.msie = true; + browser.version = 11; + detected = true; + } else if (rEdge.exec(userAgent)) { + browser.edge = true; + browser.version = userAgent.match(rEdge)[1]; + detected = true; + } else { + for (key in versionRegex) { + if (versionRegex.hasOwnProperty(key)) { + tmp = userAgent.match(versionRegex[key]); + if (tmp && tmp.length > 1) { // eslint-disable-line max-depth + browser[key] = detected = true; + browser.version = parseFloat(tmp[1] || 0); + break; + } + } + } + } + if (!detected) { + browser.others = true; + } + } + }; + + var fn = detector[appName]; + + if (fn) { + detector[appName](); + } +} + +module.exports = browser; + + +/***/ }), +/* 12 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return isMac; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return sendHostName; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return includes; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return sanitizeLinkAttribute; }); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_request_sendHostname__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(43); +/* harmony import */ var tui_code_snippet_request_sendHostname__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_request_sendHostname__WEBPACK_IMPORTED_MODULE_1__); + + +var isMac = /Mac/.test(navigator.platform); +function sendHostName() { + tui_code_snippet_request_sendHostname__WEBPACK_IMPORTED_MODULE_1___default()('editor', 'UA-129966929-1'); +} +function includes(arr, targetItem) { + return arr.indexOf(targetItem) !== -1; +} +var availableLinkAttributes = ['rel', 'target', 'contenteditable', 'hreflang', 'type']; +/** + * sanitize attribute for link + * @param {object} attribute - attribute for link + * @returns {object} sanitized attribute + */ + +function sanitizeLinkAttribute(attribute) { + if (!attribute) { + return null; + } + + var linkAttribute = {}; + availableLinkAttributes.forEach(function (key) { + if (!tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_0___default()(attribute[key])) { + linkAttribute[key] = attribute[key]; + } + }); + return linkAttribute; +} + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check element match selector + * @author NHN FE Development Lab + */ + + + +var inArray = __webpack_require__(14); +var toArray = __webpack_require__(3); + +var elProto = Element.prototype; +var matchSelector = elProto.matches || + elProto.webkitMatchesSelector || + elProto.mozMatchesSelector || + elProto.msMatchesSelector || + function(selector) { + var doc = this.document || this.ownerDocument; + + return inArray(this, toArray(doc.querySelectorAll(selector))) > -1; + }; + +/** + * Check element match selector + * @param {HTMLElement} element - element to check + * @param {string} selector - selector to check + * @returns {boolean} is selector matched to element? + * @memberof module:domUtil + */ +function matches(element, selector) { + return matchSelector.call(element, selector); +} + +module.exports = matches; + + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* eslint-disable complexity */ +/** + * @fileoverview Returns the first index at which a given element can be found in the array. + * @author NHN FE Development Lab + */ + + + +var isArray = __webpack_require__(17); + +/** + * @module array + */ + +/** + * Returns the first index at which a given element can be found in the array + * from start index(default 0), or -1 if it is not present. + * It compares searchElement to elements of the Array using strict equality + * (the same method used by the ===, or triple-equals, operator). + * @param {*} searchElement Element to locate in the array + * @param {Array} array Array that will be traversed. + * @param {number} startIndex Start index in array for searching (default 0) + * @returns {number} the First index at which a given element, or -1 if it is not present + * @memberof module:array + * @example + * var inArray = require('tui-code-snippet/array/inArray'); // node, commonjs + * + * var arr = ['one', 'two', 'three', 'four']; + * var idx1 = inArray('one', arr, 3); // -1 + * var idx2 = inArray('one', arr); // 0 + */ +function inArray(searchElement, array, startIndex) { + var i; + var length; + startIndex = startIndex || 0; + + if (!isArray(array)) { + return -1; + } + + if (Array.prototype.indexOf) { + return Array.prototype.indexOf.call(array, searchElement, startIndex); + } + + length = array.length; + for (i = startIndex; startIndex >= 0 && i < length; i += 1) { + if (array[i] === searchElement) { + return i; + } + } + + return -1; +} + +module.exports = inArray; + + +/***/ }), +/* 15 */ +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE__15__; + +/***/ }), +/* 16 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check element has specific css class + * @author NHN FE Development Lab + */ + + + +var inArray = __webpack_require__(14); +var getClass = __webpack_require__(33); + +/** + * Check element has specific css class + * @param {(HTMLElement|SVGElement)} element - target element + * @param {string} cssClass - css class + * @returns {boolean} + * @memberof module:domUtil + */ +function hasClass(element, cssClass) { + var origin; + + if (element.classList) { + return element.classList.contains(cssClass); + } + + origin = getClass(element).split(/\s+/); + + return inArray(cssClass, origin) > -1; +} + +module.exports = hasClass; + + +/***/ }), +/* 17 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is an instance of Array or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is an instance of Array or not. + * If the given variable is an instance of Array, return true. + * @param {*} obj - Target for checking + * @returns {boolean} Is array instance? + * @memberof module:type + */ +function isArray(obj) { + return obj instanceof Array; +} + +module.exports = isArray; + + +/***/ }), +/* 18 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return isNodeToBeCalculated; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return getAdditionalTopPos; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return getParentNodeObj; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return getCmRangeHeight; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return getNextEmptyLineHeight; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return getTotalOffsetTop; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return findAdjacentElementToScrollTop; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return getFallbackScrollTop; }); +/* harmony import */ var _utils_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); +/* harmony import */ var _utils_markdown__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); + + +var nestableTypes = ['list', 'blockQuote']; +var nestableTagNames = ['UL', 'OL', 'BLOCKQUOTE']; +var tableElementTagNames = ['TR', 'TH', 'TBODY', 'TD']; +function isNodeToBeCalculated(mdNode) { + return !Object(_utils_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(nestableTypes, mdNode.type); +} +function getAdditionalTopPos(scrollTop, offsetTop, currentNodeHeight, targetNodeHeight) { + var diff = (scrollTop - offsetTop) / currentNodeHeight; + return diff < 1 ? diff * targetNodeHeight : targetNodeHeight; +} +function getParentNodeObj(mdNode) { + var node = document.querySelector("[data-nodeid=\"" + mdNode.id + "\"]"); + + while (!node || Object(_utils_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(tableElementTagNames, mdNode.type) || Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_1__[/* isStyledTextNode */ "k"])(mdNode)) { + mdNode = mdNode.parent; + node = document.querySelector("[data-nodeid=\"" + mdNode.id + "\"]"); + } + + return getNonNestableNodeObj(getParentListItemObj(mdNode)); +} + +function getParentListItemObj(orgMdNode) { + var mdNode = orgMdNode; + + while (orgMdNode && orgMdNode !== 'document') { + if (orgMdNode.type === 'item') { + mdNode = orgMdNode; + break; + } + + orgMdNode = orgMdNode.parent; + } + + return { + mdNode: mdNode, + node: document.querySelector("[data-nodeid=\"" + mdNode.id + "\"]") + }; +} + +function getNonNestableNodeObj(_ref) { + var mdNode = _ref.mdNode, + node = _ref.node; + + while (Object(_utils_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(nestableTypes, mdNode.type) && mdNode.firstChild) { + mdNode = mdNode.firstChild; + node = node.firstElementChild; + } + + return { + mdNode: mdNode, + node: node + }; +} + +function getCmRangeHeight(mdNode, cm) { + var start = Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_1__[/* getMdStartLine */ "f"])(mdNode); + var end = Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_1__[/* getMdEndLine */ "d"])(mdNode); + var cmNodeHeight = cm.lineInfo(start - 1).handle.height; + var height = cm.heightAtLine(end, 'local') - cm.heightAtLine(start - 1, 'local'); + return height <= 0 ? cmNodeHeight : height + getNextEmptyLineHeight(cm, Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_1__[/* getMdEndLine */ "d"])(mdNode)); +} +function getNextEmptyLineHeight(cm, start, end) { + if (end === void 0) { + end = Number.MAX_VALUE; + } + + var lineInfo = cm.lineInfo(start); + + if (!lineInfo) { + return 0; + } + + var detailLineInfo = lineInfo.handle; + var height = 0; + + while (start <= end && !detailLineInfo.text.trim()) { + height += detailLineInfo.height; + start += 1; + detailLineInfo = cm.lineInfo(start).handle; + } + + return height; +} +function getTotalOffsetTop(el, root) { + var offsetTop = 0; + + while (el && el !== root) { + if (!Object(_utils_common__WEBPACK_IMPORTED_MODULE_0__[/* includes */ "a"])(nestableTagNames, el.tagName)) { + offsetTop += el.offsetTop; + } + + if (el.offsetParent === root.offsetParent) { + break; + } + + el = el.parentElement; + } + + return offsetTop; +} +function findAdjacentElementToScrollTop(scrollTop, root) { + var el = root; + var prev = null; + + while (el) { + var _el = el, + firstElementChild = _el.firstElementChild; + + if (!firstElementChild) { + break; + } + + var lastSibling = findLastSiblingElementToScrollTop(firstElementChild, scrollTop, getTotalOffsetTop(el, root)); + prev = el; + el = lastSibling; + } + + var adjacentEl = el || prev; + return adjacentEl === root ? null : adjacentEl; +} + +function findLastSiblingElementToScrollTop(el, scrollTop, offsetTop) { + if (el && scrollTop > offsetTop + el.offsetTop) { + return findLastSiblingElementToScrollTop(el.nextElementSibling, scrollTop, offsetTop) || el; + } + + return null; +} + +function getFallbackScrollTop(scrollInfo) { + var latestScrollTop = scrollInfo.latestScrollTop, + scrollTop = scrollInfo.scrollTop, + targetScrollTop = scrollInfo.targetScrollTop, + sourceScrollTop = scrollInfo.sourceScrollTop; + + if (latestScrollTop === null) { + return targetScrollTop; + } + + return latestScrollTop < scrollTop ? Math.max(targetScrollTop, sourceScrollTop) : Math.min(targetScrollTop, sourceScrollTop); +} + +/***/ }), +/* 19 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Bind DOM events + * @author NHN FE Development Lab + */ + + + +var isString = __webpack_require__(9); +var forEach = __webpack_require__(26); + +var safeEvent = __webpack_require__(40); + +/** + * Bind DOM events. + * @param {HTMLElement} element - element to bind events + * @param {(string|object)} types - Space splitted events names or eventName:handler object + * @param {(function|object)} handler - handler function or context for handler method + * @param {object} [context] context - context for handler method. + * @memberof module:domEvent + * @example + * var div = document.querySelector('div'); + * + * // Bind one event to an element. + * on(div, 'click', toggle); + * + * // Bind multiple events with a same handler to multiple elements at once. + * // Use event names splitted by a space. + * on(div, 'mouseenter mouseleave', changeColor); + * + * // Bind multiple events with different handlers to an element at once. + * // Use an object which of key is an event name and value is a handler function. + * on(div, { + * keydown: highlight, + * keyup: dehighlight + * }); + * + * // Set a context for handler method. + * var name = 'global'; + * var repository = {name: 'CodeSnippet'}; + * on(div, 'drag', function() { + * console.log(this.name); + * }, repository); + * // Result when you drag a div: "CodeSnippet" + */ +function on(element, types, handler, context) { + if (isString(types)) { + forEach(types.split(/\s+/g), function(type) { + bindEvent(element, type, handler, context); + }); + + return; + } + + forEach(types, function(func, type) { + bindEvent(element, type, func, handler); + }); +} + +/** + * Bind DOM events + * @param {HTMLElement} element - element to bind events + * @param {string} type - events name + * @param {function} handler - handler function or context for handler method + * @param {object} [context] context - context for handler method. + * @private + */ +function bindEvent(element, type, handler, context) { + /** + * Event handler + * @param {Event} e - event object + */ + function eventHandler(e) { + handler.call(context || element, e || window.event); + } + + if ('addEventListener' in element) { + element.addEventListener(type, eventHandler); + } else if ('attachEvent' in element) { + element.attachEvent('on' + type, eventHandler); + } + memorizeHandler(element, type, handler, eventHandler); +} + +/** + * Memorize DOM event handler for unbinding. + * @param {HTMLElement} element - element to bind events + * @param {string} type - events name + * @param {function} handler - handler function that user passed at on() use + * @param {function} wrappedHandler - handler function that wrapped by domevent for implementing some features + * @private + */ +function memorizeHandler(element, type, handler, wrappedHandler) { + var events = safeEvent(element, type); + var existInEvents = false; + + forEach(events, function(obj) { + if (obj.handler === handler) { + existInEvents = true; + + return false; + } + + return true; + }); + + if (!existInEvents) { + events.push({ + handler: handler, + wrappedHandler: wrappedHandler + }); + } +} + +module.exports = on; + + +/***/ }), +/* 20 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Unbind DOM events + * @author NHN FE Development Lab + */ + + + +var isString = __webpack_require__(9); +var forEach = __webpack_require__(26); + +var safeEvent = __webpack_require__(40); + +/** + * Unbind DOM events + * If a handler function is not passed, remove all events of that type. + * @param {HTMLElement} element - element to unbind events + * @param {(string|object)} types - Space splitted events names or eventName:handler object + * @param {function} [handler] - handler function + * @memberof module:domEvent + * @example + * // Following the example of domEvent#on + * + * // Unbind one event from an element. + * off(div, 'click', toggle); + * + * // Unbind multiple events with a same handler from multiple elements at once. + * // Use event names splitted by a space. + * off(element, 'mouseenter mouseleave', changeColor); + * + * // Unbind multiple events with different handlers from an element at once. + * // Use an object which of key is an event name and value is a handler function. + * off(div, { + * keydown: highlight, + * keyup: dehighlight + * }); + * + * // Unbind events without handlers. + * off(div, 'drag'); + */ +function off(element, types, handler) { + if (isString(types)) { + forEach(types.split(/\s+/g), function(type) { + unbindEvent(element, type, handler); + }); + + return; + } + + forEach(types, function(func, type) { + unbindEvent(element, type, func); + }); +} + +/** + * Unbind DOM events + * If a handler function is not passed, remove all events of that type. + * @param {HTMLElement} element - element to unbind events + * @param {string} type - events name + * @param {function} [handler] - handler function + * @private + */ +function unbindEvent(element, type, handler) { + var events = safeEvent(element, type); + var index; + + if (!handler) { + forEach(events, function(item) { + removeHandler(element, type, item.wrappedHandler); + }); + events.splice(0, events.length); + } else { + forEach(events, function(item, idx) { + if (handler === item.handler) { + removeHandler(element, type, item.wrappedHandler); + index = idx; + + return false; + } + + return true; + }); + events.splice(index, 1); + } +} + +/** + * Remove an event handler + * @param {HTMLElement} element - An element to remove an event + * @param {string} type - event type + * @param {function} handler - event handler + * @private + */ +function removeHandler(element, type, handler) { + if ('removeEventListener' in element) { + element.removeEventListener(type, handler); + } else if ('detachEvent' in element) { + element.detachEvent('on' + type, handler); + } +} + +module.exports = off; + + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Execute the provided callback once for each element present in the array(or Array-like object) in ascending order. + * @author NHN FE Development Lab + */ + + + +/** + * Execute the provided callback once for each element present + * in the array(or Array-like object) in ascending order. + * If the callback function returns false, the loop will be stopped. + * Callback function(iteratee) is invoked with three arguments: + * 1) The value of the element + * 2) The index of the element + * 3) The array(or Array-like object) being traversed + * @param {Array|Arguments|NodeList} arr The array(or Array-like object) that will be traversed + * @param {function} iteratee Callback function + * @param {Object} [context] Context(this) of callback function + * @memberof module:collection + * @example + * var forEachArray = require('tui-code-snippet/collection/forEachArray'); // node, commonjs + * + * var sum = 0; + * + * forEachArray([1,2,3], function(value){ + * sum += value; + * }); + * alert(sum); // 6 + */ +function forEachArray(arr, iteratee, context) { + var index = 0; + var len = arr.length; + + context = context || null; + + for (; index < len; index += 1) { + if (iteratee.call(context, arr[index], index, arr) === false) { + break; + } + } +} + +module.exports = forEachArray; + + +/***/ }), +/* 22 */ +/***/ (function(module, exports) { + +!function(e,t){for(var r in t)e[r]=t[r]}(exports,function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="/dist",r(r.s=11)}([function(e,t,r){"use strict";r.r(t),r.d(t,"__extends",(function(){return i})),r.d(t,"__assign",(function(){return o})),r.d(t,"__rest",(function(){return a})),r.d(t,"__decorate",(function(){return s})),r.d(t,"__param",(function(){return l})),r.d(t,"__metadata",(function(){return u})),r.d(t,"__awaiter",(function(){return c})),r.d(t,"__generator",(function(){return p})),r.d(t,"__createBinding",(function(){return f})),r.d(t,"__exportStar",(function(){return d})),r.d(t,"__values",(function(){return h})),r.d(t,"__read",(function(){return g})),r.d(t,"__spread",(function(){return m})),r.d(t,"__spreadArrays",(function(){return v})),r.d(t,"__await",(function(){return b})),r.d(t,"__asyncGenerator",(function(){return y})),r.d(t,"__asyncDelegator",(function(){return C})),r.d(t,"__asyncValues",(function(){return x})),r.d(t,"__makeTemplateObject",(function(){return k})),r.d(t,"__importStar",(function(){return N})),r.d(t,"__importDefault",(function(){return w})),r.d(t,"__classPrivateFieldGet",(function(){return D})),r.d(t,"__classPrivateFieldSet",(function(){return L})); +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +var n=function(e,t){return(n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)};function i(e,t){function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}var o=function(){return(o=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=0;s--)(i=e[s])&&(a=(o<3?i(a):o>3?i(t,r,a):i(t,r))||a);return o>3&&a&&Object.defineProperty(t,r,a),a}function l(e,t){return function(r,n){t(r,n,e)}}function u(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function c(e,t,r,n){return new(r||(r=Promise))((function(i,o){function a(e){try{l(n.next(e))}catch(e){o(e)}}function s(e){try{l(n.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(a,s)}l((n=n.apply(e,t||[])).next())}))}function p(e,t){var r,n,i,o,a={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function s(o){return function(s){return function(o){if(r)throw new TypeError("Generator is already executing.");for(;a;)try{if(r=1,n&&(i=2&o[0]?n.return:o[0]?n.throw||((i=n.return)&&i.call(n),0):n.next)&&!(i=i.call(n,o[1])).done)return i;switch(n=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return a.label++,{value:o[1],done:!1};case 5:a.label++,n=o[1],o=[0];continue;case 7:o=a.ops.pop(),a.trys.pop();continue;default:if(!(i=a.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function g(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,i,o=r.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(n=o.next()).done;)a.push(n.value)}catch(e){i={error:e}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(i)throw i.error}}return a}function m(){for(var e=[],t=0;t1||s(e,t)}))})}function s(e,t){try{(r=i[e](t)).value instanceof b?Promise.resolve(r.value.v).then(l,u):c(o[0][2],r)}catch(e){c(o[0][3],e)}var r}function l(e){s("next",e)}function u(e){s("throw",e)}function c(e,t){e(t),o.shift(),o.length&&s(o[0][0],o[0][1])}}function C(e){var t,r;return t={},n("next"),n("throw",(function(e){throw e})),n("return"),t[Symbol.iterator]=function(){return this},t;function n(n,i){t[n]=e[n]?function(t){return(r=!r)?{value:b(e[n](t)),done:"return"===n}:i?i(t):t}:i}}function x(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,r=e[Symbol.asyncIterator];return r?r.call(e):(e=h(e),t={},n("next"),n("throw"),n("return"),t[Symbol.asyncIterator]=function(){return this},t);function n(r){t[r]=e[r]&&function(t){return new Promise((function(n,i){(function(e,t,r,n){Promise.resolve(n).then((function(t){e({value:t,done:r})}),t)})(n,i,(t=e[r](t)).done,t.value)}))}}}function k(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}function N(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t}function w(e){return e&&e.__esModule?e:{default:e}}function D(e,t){if(!t.has(e))throw new TypeError("attempted to get private field on non-instance");return t.get(e)}function L(e,t,r){if(!t.has(e))throw new TypeError("attempted to set private field on non-instance");return t.set(e,r),r}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.text=t.isRefDef=t.isTable=t.isList=t.isHeading=t.isHtmlBlock=t.isCodeBlock=t.createNode=t.RefDefNode=t.TableCellNode=t.TableNode=t.CodeNode=t.HtmlBlockNode=t.CodeBlockNode=t.LinkNode=t.HeadingNode=t.ListNode=t.BlockNode=t.Node=t.removeAllNode=t.removeNodeById=t.getNodeById=t.isContainer=void 0;var n=r(0),i=n.__importDefault(r(18));function o(e){switch(e.type){case"document":case"blockQuote":case"list":case"item":case"paragraph":case"heading":case"emph":case"strong":case"strike":case"link":case"image":case"table":case"tableHead":case"tableBody":case"tableRow":case"tableCell":case"tableDelimRow":return!0;default:return!1}}t.isContainer=o;var a=1,s={};t.getNodeById=function(e){return s[e]},t.removeNodeById=function(e){delete s[e]},t.removeAllNode=function(){s={}};var l=function(){function e(e,t){this.parent=null,this.prev=null,this.next=null,this.firstChild=null,this.lastChild=null,this.literal=null,this.id="document"===e?-1:a++,this.type=e,this.sourcepos=t,s[this.id]=this}return e.prototype.isContainer=function(){return o(this)},e.prototype.unlink=function(){this.prev?this.prev.next=this.next:this.parent&&(this.parent.firstChild=this.next),this.next?this.next.prev=this.prev:this.parent&&(this.parent.lastChild=this.prev),this.parent=null,this.next=null,this.prev=null},e.prototype.replaceWith=function(e){this.insertBefore(e),this.unlink()},e.prototype.insertAfter=function(e){e.unlink(),e.next=this.next,e.next&&(e.next.prev=e),e.prev=this,this.next=e,this.parent&&(e.parent=this.parent,e.next||(e.parent.lastChild=e))},e.prototype.insertBefore=function(e){e.unlink(),e.prev=this.prev,e.prev&&(e.prev.next=e),e.next=this,this.prev=e,e.parent=this.parent,e.prev||(e.parent.firstChild=e)},e.prototype.appendChild=function(e){e.unlink(),e.parent=this,this.lastChild?(this.lastChild.next=e,e.prev=this.lastChild,this.lastChild=e):(this.firstChild=e,this.lastChild=e)},e.prototype.prependChild=function(e){e.unlink(),e.parent=this,this.firstChild?(this.firstChild.prev=e,e.next=this.firstChild,this.firstChild=e):(this.firstChild=e,this.lastChild=e)},e.prototype.walker=function(){return new i.default(this)},e}();t.Node=l;var u=function(e){function t(t,r){var n=e.call(this,t,r)||this;return n.open=!0,n.lineOffsets=null,n.stringContent=null,n.lastLineBlank=!1,n.lastLineChecked=!1,n.customType=null,n.type=t,n}return n.__extends(t,e),t}(l);t.BlockNode=u;var c=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.listData=null,t}return n.__extends(t,e),t}(u);t.ListNode=c;var p=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.level=0,t.headingType="atx",t}return n.__extends(t,e),t}(u);t.HeadingNode=p;var f=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.destination=null,t.title=null,t.extendedAutolink=!1,t}return n.__extends(t,e),t}(l);t.LinkNode=f;var d=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.isFenced=!1,t.fenceChar=null,t.fenceLength=0,t.fenceOffset=-1,t.info=null,t.infoPadding=0,t}return n.__extends(t,e),t}(u);t.CodeBlockNode=d;var h=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.htmlBlockType=-1,t}return n.__extends(t,e),t}(u);t.HtmlBlockNode=h;var g=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.tickCount=0,t}return n.__extends(t,e),t}(l);t.CodeNode=g;var m=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.columns=[],t}return n.__extends(t,e),t}(u);t.TableNode=m;var v=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.startIdx=0,t.endIdx=0,t.paddingLeft=0,t.paddingRight=0,t.ignored=!1,t}return n.__extends(t,e),t}(u);t.TableCellNode=v;var b=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.title="",t.dest="",t.label="",t}return n.__extends(t,e),t}(u);function y(e,t){switch(e){case"heading":return new p(e,t);case"list":case"item":return new c(e,t);case"link":case"image":return new f(e,t);case"codeBlock":return new d(e,t);case"htmlBlock":return new h(e,t);case"table":return new m(e,t);case"tableCell":return new v(e,t);case"document":case"paragraph":case"blockQuote":case"thematicBreak":case"tableRow":case"tableBody":case"tableHead":return new u(e,t);case"code":return new g(e,t);case"refDef":return new b(e,t);default:return new l(e,t)}}t.RefDefNode=b,t.createNode=y,t.isCodeBlock=function(e){return"codeBlock"===e.type},t.isHtmlBlock=function(e){return"htmlBlock"===e.type},t.isHeading=function(e){return"heading"===e.type},t.isList=function(e){return"list"===e.type},t.isTable=function(e){return"table"===e.type},t.isRefDef=function(e){return"refDef"===e.type},t.text=function(e,t){var r=y("text",t);return r.literal=e,r}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isEmpty=t.last=t.repeat=t.escapeXml=t.normalizeURI=t.unescapeString=t.ESCAPABLE=t.ENTITY=void 0;var n=r(0).__importDefault(r(12)),i=r(8);t.ENTITY="&(?:#x[a-f0-9]{1,6}|#[0-9]{1,7}|[a-z][a-z0-9]{1,31});";var o=/[\\&]/;t.ESCAPABLE="[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]";var a=new RegExp("\\\\"+t.ESCAPABLE+"|"+t.ENTITY,"gi"),s=new RegExp('[&<>"]',"g"),l=function(e){return 92===e.charCodeAt(0)?e.charAt(1):i.decodeHTML(e)};function u(e){switch(e){case"&":return"&";case"<":return"<";case">":return">";case'"':return""";default:return e}}t.unescapeString=function(e){return o.test(e)?e.replace(a,l):e},t.normalizeURI=function(e){try{return n.default(e)}catch(t){return e}},t.escapeXml=function(e){return s.test(e)?e.replace(s,u):e},t.repeat=function(e,t){for(var r=[],n=0;nt&&(t+=1),this.root.sourcepos[1]=[t+1,e[t].length]},e.prototype.replaceRangeNodes=function(e,t,r){e?(a.insertNodesBefore(e,r),a.removeNextUntil(e,t),[e.id,t.id].forEach((function(e){return o.removeNodeById(e)})),e.unlink()):t?(a.insertNodesBefore(t,r),o.removeNodeById(t.id),t.unlink()):a.prependChildNodes(this.root,r)},e.prototype.getNodeRange=function(e,t){var r=a.findChildNodeAtLine(this.root,e[0]),n=a.findChildNodeAtLine(this.root,t[0]);return n&&n.next&&t[0]+1===n.next.sourcepos[0][0]&&(n=n.next),a.getRangeForCustomType(r,n)},e.prototype.trigger=function(e,t){this.eventHandlerMap[e].forEach((function(e){e(t)}))},e.prototype.extendEndLine=function(e){for(;""===this.lineTexts[e];)e+=1;return e},e.prototype.parseRange=function(e,t,r,n){var i;e&&e.prev&&(o.isList(e.prev)&&function(e){var t=e.match(/^[ \t]+/);if(t&&(t[0].length>=2||/\t/.test(t[0])))return!0;var r=t?e.slice(t.length):e;return s.reBulletListMarker.test(r)||s.reOrderedListMarker.test(r)}(this.lineTexts[r-1])||o.isTable(e.prev)&&(i=this.lineTexts[r-1],!u.isBlank(i)&&-1!==i.indexOf("|")))&&(r=(e=e.prev).sourcepos[0][0]);for(var l=this.lineTexts.slice(r-1,n),c=this.parser.partialParseStart(r,l),p=t?t.next:this.root.firstChild,f=c.lastChild,d=f&&o.isCodeBlock(f),h=f&&o.isList(f);d&&p||h&&p&&("list"===p.type||p.sourcepos[0][1]>=2);){var g=this.extendEndLine(p.sourcepos[1][0]);this.parser.partialParseExtends(this.lineTexts.slice(n,g)),e||(e=t),t=p,n=g,p=p.next}return this.parser.partialParseFinish(),{newNodes:a.getChildNodes(c),extStartNode:e,extEndNode:t}},e.prototype.getRemovedNodeRange=function(e,t){return!e||e&&o.isRefDef(e)||t&&o.isRefDef(t)?null:{id:[e.id,t.id],line:[e.sourcepos[0][0]-1,t.sourcepos[1][0]-1]}},e.prototype.markDeletedRefMap=function(e,t){var r=this;if(!l.isEmptyObj(this.refMap)){var n=function(e){if(o.isRefDef(e)){var t=r.refMap[e.label];t&&e.id===t.id&&(t.unlinked=!0)}};e&&a.invokeNextUntil(n,e.parent,t),t&&a.invokeNextUntil(n,t)}},e.prototype.replaceWithNewRefDefState=function(e){var t=this;if(!l.isEmptyObj(this.refMap)){var r=function(e){if(o.isRefDef(e)){var r=e.label,n=t.refMap[r];n&&!n.unlinked||(t.refMap[r]=p(e))}};e.forEach((function(e){a.invokeNextUntil(r,e)}))}},e.prototype.replaceWithRefDefCandidate=function(){var e=this;l.isEmptyObj(this.refDefCandidateMap)||l.iterateObject(this.refDefCandidateMap,(function(t,r){var n=r.label,i=r.sourcepos,o=e.refMap[n];(!o||o.unlinked||o.sourcepos[0][0]>i[0][0])&&(e.refMap[n]=p(r))}))},e.prototype.getRangeWithRefDef=function(e,t,r,n,i){if(this.referenceDefinition&&!l.isEmptyObj(this.refMap)){var s=a.findChildNodeAtLine(this.root,e-1),u=a.findChildNodeAtLine(this.root,t+1);s&&o.isRefDef(s)&&s!==r&&s!==n&&(e=(r=s).sourcepos[0][0]),u&&o.isRefDef(u)&&u!==r&&u!==n&&(n=u,t=this.extendEndLine(n.sourcepos[1][0]+i))}return[r,n,e,t]},e.prototype.parseWithFrontMatter=function(e,t,r){void 0===r&&(r=0);var i=n.__spreadArrays(this.lineTexts),o=c.getFrontMatterPos(this.lineTexts),a=o[0],s=o[1];a>-1&&s>-1&&(this.lineTexts[a]=c.frontMatterOpen,this.lineTexts[s]=c.frontMatterClose,a>=t[0]-1&&(t[0]=s+1),a<=e[0]-1&&s>=t[0]-1&&(e[0]=a+1,t[0]=s+1));var l=this.parse(e,t,r);return this.lineTexts=i,l},e.prototype.parse=function(e,t,r){void 0===r&&(r=0);var n=this.getNodeRange(e,t),i=n[0],o=n[1],a=i?Math.min(i.sourcepos[0][0],e[0]):e[0],s=this.extendEndLine((o?Math.max(o.sourcepos[1][0],t[0]):t[0])+r),l=this.parseRange.apply(this,this.getRangeWithRefDef(a,s,i,o,r)),u=l.newNodes,c=l.extStartNode,p=l.extEndNode,f=this.getRemovedNodeRange(c,p),d=p?p.next:this.root.firstChild;return this.referenceDefinition?(this.markDeletedRefMap(c,p),this.replaceRangeNodes(c,p,u),this.replaceWithNewRefDefState(u)):this.replaceRangeNodes(c,p,u),{nodes:u,removedNodeRange:f,nextNode:d}},e.prototype.parseRefLink=function(){var e=this,t=[];return l.isEmptyObj(this.refMap)||l.iterateObject(this.refMap,(function(r,n){n.unlinked&&delete e.refMap[r],l.iterateObject(e.refLinkCandidateMap,(function(n,i){var o=i.node;i.refLabel===r&&t.push(e.parse(o.sourcepos[0],o.sourcepos[1]))}))})),t},e.prototype.removeUnlinkedCandidate=function(){l.isEmptyObj(this.refDefCandidateMap)||[this.refLinkCandidateMap,this.refDefCandidateMap].forEach((function(e){l.iterateObject(e,(function(t){a.isUnlinked(t)&&delete e[t]}))}))},e.prototype.editMarkdown=function(e,t,r){var n=this.updateLineTexts(e,t,r),i=this.frontMatter?this.parseWithFrontMatter(e,t,n):this.parse(e,t,n),o=l.omit(i,"nextNode");a.updateNextLineNumbers(i.nextNode,n),this.updateRootNodeState();var s=[o];return this.referenceDefinition&&(this.removeUnlinkedCandidate(),this.replaceWithRefDefCandidate(),s=s.concat(this.parseRefLink())),this.trigger("change",s),s},e.prototype.getLineTexts=function(){return this.lineTexts},e.prototype.getRootNode=function(){return this.root},e.prototype.findNodeAtPosition=function(e){var t=a.findNodeAtPosition(this.root,e);return t&&t!==this.root?t:null},e.prototype.findFirstNodeAtLine=function(e){return a.findFirstNodeAtLine(this.root,e)},e.prototype.on=function(e,t){this.eventHandlerMap[e].push(t)},e.prototype.off=function(e,t){var r=this.eventHandlerMap[e],n=r.indexOf(t);r.splice(n,1)},e.prototype.findNodeById=function(e){return a.findNodeById(e)},e.prototype.removeAllNode=function(){o.removeAllNode()},e}();t.ToastMark=f},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getFrontMatterPos=t.replaceFrontMatter=t.frontMatterClose=t.frontMatterOpen=void 0,t.frontMatterOpen="{:f",t.frontMatterClose="f:}";var n=/^---$/,i=/^---$([\s\S]*)^---$/m;t.replaceFrontMatter=function(e){var r=e.trim();return/^---/.test(r)&&function(e){return i.test(e)}(r)?e.replace(i,t.frontMatterOpen+"$1"+t.frontMatterClose):e},t.getFrontMatterPos=function(e){for(var t=-1,r=-1,i=0;i0)break;n.test(o)&&(t<0?t=i:r=i)}return[t,r]}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Parser=void 0;var n=r(0),i=r(2),o=r(1),a=r(19),s=r(22),l=r(4),u=r(10),c=r(3),p=r(6),f=r(26),d=[/./,/<\/(?:script|pre|style)>/i,/-->/,/\?>/,/>/,/\]\]>/],h=/^[#`~*+_=<>0-9-]/,g=/\r\n|\n|\r/;function m(){return o.createNode("document",[[1,1],[0,0]])}var v={smart:!1,tagFilter:!1,extendedAutolinks:!1,disallowedHtmlBlockTags:[],referenceDefinition:!1,disallowDeepHeading:!1,customParser:null,frontMatter:!1},b=function(){function e(e){this.options=n.__assign(n.__assign({},v),e),this.doc=m(),this.tip=this.doc,this.oldtip=this.doc,this.lineNumber=0,this.offset=0,this.column=0,this.nextNonspace=0,this.nextNonspaceColumn=0,this.indent=0,this.currentLine="",this.indented=!1,this.blank=!1,this.partiallyConsumedTab=!1,this.allClosed=!0,this.lastMatchedContainer=this.doc,this.refMap={},this.refLinkCandidateMap={},this.refDefCandidateMap={},this.lastLineLength=0,this.options.frontMatter&&(this.options.customParser=n.__assign(n.__assign({},f.frontMatterParser),this.options.customParser)),this.inlineParser=new a.InlineParser(this.options)}return e.prototype.advanceOffset=function(e,t){void 0===t&&(t=!1);for(var r,n,i,o=this.currentLine;e>0&&(i=o[this.offset]);)"\t"===i?(r=4-this.column%4,t?(this.partiallyConsumedTab=r>e,n=r>e?e:r,this.column+=n,this.offset+=this.partiallyConsumedTab?0:1,e-=n):(this.partiallyConsumedTab=!1,this.column+=r,this.offset+=1,e-=1)):(this.partiallyConsumedTab=!1,this.offset+=1,this.column+=1,e-=1)},e.prototype.advanceNextNonspace=function(){this.offset=this.nextNonspace,this.column=this.nextNonspaceColumn,this.partiallyConsumedTab=!1},e.prototype.findNextNonspace=function(){for(var e,t=this.currentLine,r=this.offset,n=this.column;""!==(e=t.charAt(r));)if(" "===e)r++,n++;else{if("\t"!==e)break;r++,n+=4-n%4}this.blank="\n"===e||"\r"===e||""===e,this.nextNonspace=r,this.nextNonspaceColumn=n,this.indent=this.nextNonspaceColumn-this.column,this.indented=this.indent>=l.CODE_INDENT},e.prototype.addLine=function(){if(this.partiallyConsumedTab){this.offset+=1;var e=4-this.column%4;this.tip.stringContent+=i.repeat(" ",e)}this.tip.lineOffsets?this.tip.lineOffsets.push(this.offset):this.tip.lineOffsets=[this.offset],this.tip.stringContent+=this.currentLine.slice(this.offset)+"\n"},e.prototype.addChild=function(e,t){for(;!s.blockHandlers[this.tip.type].canContain(e);)this.finalize(this.tip,this.lineNumber-1);var r=t+1,n=o.createNode(e,[[this.lineNumber,r],[0,0]]);return n.stringContent="",this.tip.appendChild(n),this.tip=n,n},e.prototype.closeUnmatchedBlocks=function(){if(!this.allClosed){for(;this.oldtip!==this.lastMatchedContainer;){var e=this.oldtip.parent;this.finalize(this.oldtip,this.lineNumber-1),this.oldtip=e}this.allClosed=!0}},e.prototype.finalize=function(e,t){var r=e.parent;e.open=!1,e.sourcepos[1]=[t,this.lastLineLength],s.blockHandlers[e.type].finalize(this,e),this.tip=r},e.prototype.processInlines=function(e){var t,r=this.options.customParser,n=e.walker();for(this.inlineParser.refMap=this.refMap,this.inlineParser.refLinkCandidateMap=this.refLinkCandidateMap,this.inlineParser.refDefCandidateMap=this.refDefCandidateMap,this.inlineParser.options=this.options;t=n.next();){var i=t.node,o=t.entering,a=i.type;r&&r[a]&&r[a](i,{entering:o,options:this.options}),o||"paragraph"!==a&&"heading"!==a&&("tableCell"!==a||i.ignored)||this.inlineParser.parse(i)}},e.prototype.incorporateLine=function(e){var t=this.doc;this.oldtip=this.tip,this.offset=0,this.column=0,this.blank=!1,this.partiallyConsumedTab=!1,this.lineNumber+=1,-1!==e.indexOf("\0")&&(e=e.replace(/\0/g,"�")),this.currentLine=e;for(var r,n=!0;(r=t.lastChild)&&r.open;){switch(t=r,this.findNextNonspace(),s.blockHandlers[t.type].continue(this,t)){case 0:break;case 1:n=!1;break;case 2:return void(this.lastLineLength=e.length);default:throw new Error("continue returned illegal value, must be 0, 1, or 2")}if(!n){t=t.parent;break}}this.allClosed=t===this.oldtip,this.lastMatchedContainer=t;for(var i="paragraph"!==t.type&&s.blockHandlers[t.type].acceptsLines,a=u.blockStarts.length;!i;){if(this.findNextNonspace(),"table"!==t.type&&"tableBody"!==t.type&&"paragraph"!==t.type&&!this.indented&&!h.test(e.slice(this.nextNonspace))){this.advanceNextNonspace();break}for(var l=0;l=1&&t.htmlBlockType<=5&&d[t.htmlBlockType].test(this.currentLine.slice(this.offset))&&(this.lastLineLength=e.length,this.finalize(t,this.lineNumber))):this.offset`\\x00-\\x20]+|'[^']*'|\"[^\"]*\"))?)*\\s*/?>",t.CLOSETAG="]";var n="(?:"+t.OPENTAG+"|"+t.CLOSETAG+"|\x3c!----\x3e|\x3c!--(?:-?[^>-])(?:-?[^-])*--\x3e|[<][?].*?[?][>]|]*>|)";t.reHtmlTag=new RegExp("^"+n,"i")},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.blockStarts=t.reOrderedListMarker=t.reBulletListMarker=void 0;var n=r(1),i=r(9),o=r(4),a=r(25),s=/^`{3,}(?!.*`)|^~{3,}/,l=[/./,/^<(?:script|pre|style)(?:\s|>|$)/i,/^/g, ''); + root.innerHTML = html; + } else { + root.appendChild(html); + } + + removeUnnecessaryTags(root); + leaveOnlyWhitelistAttribute(root); + return _utils_dom__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"].finalizeHtml(root, needHtmlText); +} +/** + * Removes unnecessary tags. + * @param {HTMLElement} html - root element + * @private + */ + + +function removeUnnecessaryTags(html) { + var removedTags = _utils_dom__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"].findAll(html, 'script, iframe, textarea, form, button, select, input, meta, style, link, title, embed, object, details, summary'); + removedTags.forEach(function (node) { + _utils_dom__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"].remove(node); + }); +} +/** + * Checks whether the attribute and value that causing XSS or not. + * @param {string} attrName - name of attribute + * @param {string} attrValue - value of attirbute + * @param {boolean} state + * @private + */ + + +function isXSSAttribute(attrName, attrValue) { + return attrName.match(XSS_ATTR_RX) && attrValue.match(XSS_VALUE_RX); +} +/** + * Removes attributes of blacklist from node. + * @param {HTMLElement} node - node to remove attributes + * @param {NamedNodeMap} blacklistAttrs - attributes of blacklist + * @private + */ + + +function removeBlacklistAttributes(node, blacklistAttrs) { + tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(blacklistAttrs).forEach(function (_ref) { + var name = _ref.name; + + if (ON_EVENT_RX.test(name)) { + node[name] = null; + } + + if (node.getAttribute(name)) { + node.removeAttribute(name); + } + }); +} +/** + * Leaves only white list attributes. + * @param {HTMLElement} html - root element + * @private + */ + + +function leaveOnlyWhitelistAttribute(html) { + _utils_dom__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"].findAll(html, '*').forEach(function (node) { + var attributes = node.attributes; + var blacklist = tui_code_snippet_collection_toArray__WEBPACK_IMPORTED_MODULE_0___default()(attributes).filter(function (attr) { + var name = attr.name, + value = attr.value; + var htmlAttr = name.match(HTML_ATTR_LIST_RX); + var svgAttr = name.match(SVG_ATTR_LIST_RX); + var xssAttr = htmlAttr && isXSSAttribute(name, value); + return !htmlAttr && !svgAttr || xssAttr; + }); + removeBlacklistAttributes(node, blacklist); + }); +} + +/* harmony default export */ __webpack_exports__["a"] = (htmlSanitizer); + +/***/ }), +/* 26 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Execute the provided callback once for each property of object(or element of array) which actually exist. + * @author NHN FE Development Lab + */ + + + +var isArray = __webpack_require__(17); +var forEachArray = __webpack_require__(21); +var forEachOwnProperties = __webpack_require__(10); + +/** + * @module collection + */ + +/** + * Execute the provided callback once for each property of object(or element of array) which actually exist. + * If the object is Array-like object(ex-arguments object), It needs to transform to Array.(see 'ex2' of example). + * If the callback function returns false, the loop will be stopped. + * Callback function(iteratee) is invoked with three arguments: + * 1) The value of the property(or The value of the element) + * 2) The name of the property(or The index of the element) + * 3) The object being traversed + * @param {Object} obj The object that will be traversed + * @param {function} iteratee Callback function + * @param {Object} [context] Context(this) of callback function + * @memberof module:collection + * @example + * var forEach = require('tui-code-snippet/collection/forEach'); // node, commonjs + * + * var sum = 0; + * + * forEach([1,2,3], function(value){ + * sum += value; + * }); + * alert(sum); // 6 + * + * // In case of Array-like object + * var array = Array.prototype.slice.call(arrayLike); // change to array + * forEach(array, function(value){ + * sum += value; + * }); + */ +function forEach(obj, iteratee, context) { + if (isArray(obj)) { + forEachArray(obj, iteratee, context); + } else { + forEachOwnProperties(obj, iteratee, context); + } +} + +module.exports = forEach; + + +/***/ }), +/* 27 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is a function or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is a function or not. + * If the given variable is a function, return true. + * @param {*} obj - Target for checking + * @returns {boolean} Is function? + * @memberof module:type + */ +function isFunction(obj) { + return obj instanceof Function; +} + +module.exports = isFunction; + + +/***/ }), +/* 28 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is existing or not. + * @author NHN FE Development Lab + */ + + + +var isUndefined = __webpack_require__(8); +var isNull = __webpack_require__(48); + +/** + * Check whether the given variable is existing or not. + * If the given variable is not null and not undefined, returns true. + * @param {*} param - Target for checking + * @returns {boolean} Is existy? + * @memberof module:type + * @example + * var isExisty = require('tui-code-snippet/type/isExisty'); // node, commonjs + * + * isExisty(''); //true + * isExisty(0); //true + * isExisty([]); //true + * isExisty({}); //true + * isExisty(null); //false + * isExisty(undefined); //false +*/ +function isExisty(param) { + return !isUndefined(param) && !isNull(param); +} + +module.exports = isExisty; + + +/***/ }), +/* 29 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return getHTMLRenderConvertors; }); +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +var baseConvertors = { + paragraph: function paragraph(node, _ref) { + var entering = _ref.entering, + origin = _ref.origin, + options = _ref.options; + var nodeId = options.nodeId, + _options$customProp = options.customProp, + customProp = _options$customProp === void 0 ? {} : _options$customProp; + var showFrontMatter = customProp.showFrontMatter && node.customType; // prevent paragraph from being removed when it's child of tight list item + // to show highlight style in live-preview mode + + if (nodeId && !node.customType || showFrontMatter) { + return { + type: entering ? 'openTag' : 'closeTag', + outerNewLine: true, + tagName: 'p' + }; + } + + return origin(); + }, + softbreak: function softbreak(node) { + var isPrevNodeHTML = node.prev && node.prev.type === 'htmlInline'; + var isPrevBR = isPrevNodeHTML && /
      /.test(node.prev.literal); + var content = isPrevBR ? '\n' : '
      \n'; + return { + type: 'html', + content: content + }; + }, + item: function item(node, _ref2) { + var entering = _ref2.entering; + + if (entering) { + var attributes = {}; + var classNames = []; + + if (node.listData.task) { + attributes['data-te-task'] = ''; + classNames.push('task-list-item'); + + if (node.listData.checked) { + classNames.push('checked'); + } + } + + return { + type: 'openTag', + tagName: 'li', + classNames: classNames, + attributes: attributes, + outerNewLine: true + }; + } + + return { + type: 'closeTag', + tagName: 'li', + outerNewLine: true + }; + }, + code: function code(node) { + var attributes = { + 'data-backticks': node.tickCount + }; + return [{ + type: 'openTag', + tagName: 'code', + attributes: attributes + }, { + type: 'text', + content: node.literal + }, { + type: 'closeTag', + tagName: 'code' + }]; + }, + codeBlock: function codeBlock(node) { + var infoWords = node.info ? node.info.split(/\s+/) : []; + var preClasses = []; + var codeAttrs = {}; + + if (node.fenceLength > 3) { + codeAttrs['data-backticks'] = node.fenceLength; + } + + if (infoWords.length > 0 && infoWords[0].length > 0) { + var lang = infoWords[0]; + preClasses.push("lang-" + lang); + codeAttrs['data-language'] = lang; + } + + return [{ + type: 'openTag', + tagName: 'pre', + classNames: preClasses + }, { + type: 'openTag', + tagName: 'code', + attributes: codeAttrs + }, { + type: 'text', + content: node.literal + }, { + type: 'closeTag', + tagName: 'code' + }, { + type: 'closeTag', + tagName: 'pre' + }]; + } +}; +function getHTMLRenderConvertors(linkAttribute, customConvertors) { + var convertors = _extends({}, baseConvertors); + + if (linkAttribute) { + convertors.link = function (_, _ref3) { + var entering = _ref3.entering, + origin = _ref3.origin; + var result = origin(); + + if (entering) { + result.attributes = _extends({}, result.attributes, linkAttribute); + } + + return result; + }; + } + + if (customConvertors) { + Object.keys(customConvertors).forEach(function (nodeType) { + var orgConvertor = convertors[nodeType]; + var customConvertor = customConvertors[nodeType]; + + if (orgConvertor) { + convertors[nodeType] = function (node, context) { + var newContext = _extends({}, context); + + newContext.origin = function () { + return orgConvertor(node, context); + }; + + return customConvertor(node, newContext); + }; + } else { + convertors[nodeType] = customConvertor; + } + }); + } + + return convertors; +} + +/***/ }), +/* 30 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export CodeBlockManager */ +/** + * @fileoverview Implements CodeBlockManager + * @author NHN FE Development Lab + */ + +/** + * Class Code Block Manager + */ +var CodeBlockManager = /*#__PURE__*/function () { + function CodeBlockManager() { + this._replacers = {}; + } + /** + * Set replacer for code block + * @param {string} language - code block language + * @param {function} replacer - replacer function to code block element + */ + + + var _proto = CodeBlockManager.prototype; + + _proto.setReplacer = function setReplacer(language, replacer) { + language = language.toLowerCase(); + this._replacers[language] = replacer; + } + /** + * get replacer for code block + * @param {string} language - code block type + * @returns {function} - replacer function + */ + ; + + _proto.getReplacer = function getReplacer(language) { + return this._replacers[language]; + } + /** + * Create code block html. + * @param {string} language - code block language + * @param {string} codeText - code text + * @returns {string} + */ + ; + + _proto.createCodeBlockHtml = function createCodeBlockHtml(language, codeText) { + language = language.toLowerCase(); + var replacer = this.getReplacer(language); + + if (replacer) { + return replacer(codeText, language); + } + + return escape(codeText, false); + }; + + return CodeBlockManager; +}(); +/** + * escape code from markdown-it + * @param {string} html HTML string + * @param {string} encode Boolean value of whether encode or not + * @returns {string} + * @ignore + */ + + +function escape(html, encode) { + return html.replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, '''); +} + + +/* harmony default export */ __webpack_exports__["a"] = (new CodeBlockManager()); + +/***/ }), +/* 31 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return invokePlugins; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return getPluginInfo; }); +/* harmony import */ var tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(17); +/* harmony import */ var tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_type_isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(27); +/* harmony import */ var tui_code_snippet_type_isFunction__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isFunction__WEBPACK_IMPORTED_MODULE_1__); +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + + + +/** + * Invoke plugins + * @param {Array.} plugins - list of plugin function only or + * plugin function with options + * @param {Editor|Viewer} editor - editor or viewer instance + */ + +function invokePlugins(plugins, editor) { + plugins.forEach(function (plugin) { + if (tui_code_snippet_type_isFunction__WEBPACK_IMPORTED_MODULE_1___default()(plugin)) { + plugin(editor); + } else if (tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0___default()(plugin)) { + var pluginFn = plugin[0], + _plugin$ = plugin[1], + options = _plugin$ === void 0 ? {} : _plugin$; + pluginFn(editor, options); + } + }); +} +/** + * Get plugin info + * @param {Array.} plugins - list of plugin function only or + * plugin function with options + * @returns {Object} - plugin info + */ + +function getPluginInfo(plugins) { + if (!plugins) { + return {}; + } + + return plugins.reduce(function (acc, plugin) { + var pluginInfo = tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0___default()(plugin) ? plugin[0] : plugin; + + if (!tui_code_snippet_type_isFunction__WEBPACK_IMPORTED_MODULE_1___default()(pluginInfo)) { + var renderer = pluginInfo.renderer, + parser = pluginInfo.parser, + pluginFn = pluginInfo.pluginFn; + plugin = tui_code_snippet_type_isArray__WEBPACK_IMPORTED_MODULE_0___default()(plugin) ? [pluginFn, plugin[1]] : pluginFn; + + if (renderer) { + acc.renderer = _extends({}, acc.renderer, renderer); + } + + if (parser) { + acc.parser = _extends({}, acc.parser, parser); + } + } + + acc.plugins.push(plugin); + return acc; + }, { + plugins: [], + renderer: {}, + parser: {} + }); +} + +/***/ }), +/* 32 */ +/***/ (function(module, exports, __webpack_require__) { + +/*! + * to-mark + * @version 1.0.1 | Tue Nov 24 2020 + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(true) + module.exports = factory(); + else {} +})(window, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +// ESM COMPAT FLAG +__webpack_require__.r(__webpack_exports__); + +// CONCATENATED MODULE: ./src/domRunner.js +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview Implements DomRunner + * @author NHN Ent. FE Development Lab + */ +var NODE = { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3 +}; +/** + * DomRunner + * @param {HTMLElement} node A root node that it has nodes to iterate(not iterate itself and its any siblings) + * @class + */ + +var DomRunner = /*#__PURE__*/function () { + function DomRunner(node) { + this._normalizeTextChildren(node); + + this._root = node; + this._current = node; + } + /** + * Iterate next node + * @returns {HTMLElement} next node + */ + + + var _proto = DomRunner.prototype; + + _proto.next = function next() { + var current = this._current; + var node; + + if (this._current) { + node = this._getNextNode(current); + + while (this._isNeedNextSearch(node, current)) { + current = current.parentNode; + node = current.nextSibling; + } + + this._current = node; + } + + return this._current; + } + /** + * Return current node + * @returns {HTMLElement} current node + */ + ; + + _proto.getNode = function getNode() { + this._normalizeTextChildren(this._current); + + return this._current; + }; + + _proto._normalizeTextChildren = function _normalizeTextChildren(node) { + if (!node || node.childNodes.length < 2) { + return; + } + + var childNode = node.firstChild; + var nextNode; + + while (childNode.nextSibling) { + nextNode = childNode.nextSibling; + + if (childNode.nodeType === NODE.TEXT_NODE && nextNode.nodeType === NODE.TEXT_NODE) { + childNode.nodeValue += nextNode.nodeValue; + node.removeChild(nextNode); + } else { + childNode = nextNode; + } + } + } + /** + * Get current node's text content + * @returns {string} text + */ + ; + + _proto.getNodeText = function getNodeText() { + var node = this.getNode(); + var text; + + if (node.nodeType === NODE.TEXT_NODE) { + text = node.nodeValue; + } else { + text = node.textContent || node.innerText; + } + + return text; + } + /** + * Check if there is next node to iterate + * @private + * @param {HTMLElement} node next node + * @param {HTMLElement} current next node + * @returns {boolean} result + */ + ; + + _proto._isNeedNextSearch = function _isNeedNextSearch(node, current) { + return !node && current !== this._root && current.parentNode !== this._root; + } + /** + * Return available next node + * @private + * @param {HTMLElement} current current node + * @returns {node} next node + */ + ; + + _proto._getNextNode = function _getNextNode(current) { + return current.firstChild || current.nextSibling; + }; + + return DomRunner; +}(); + +_defineProperty(DomRunner, "NODE_TYPE", NODE); + + +// CONCATENATED MODULE: ./src/toDom.js +/** + * @fileoverview Implements toDom + * @author NHN Ent. FE Development Lab + */ +var FIND_FIRST_LAST_SPACE_OR_RETURN_OR_TAB_RX = /^[\s\r\n\t]+|[\s\r\n\t]+$/g; +var FIND_RETURN_OR_TAB_BETWEEN_TAGS_RX = />[\r\n\t]+[ ]+<'); // remove spaces more than 1(if need more space, must use  ) + + html = html.replace(FIND_WHOLE_SPACE_MORE_THAN_ONE_BETWEEN_TAGS_RX, '> <'); + return html; +} + +toDom.preProcess = preProcess; +// CONCATENATED MODULE: ./src/renderer.js +function renderer_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview Implements Renderer + * @author NHN Ent. FE Development Lab + */ +var FIND_LEAD_SPACE_RX = /^\u0020/; +var FIND_TRAIL_SPACE_RX = /.+\u0020$/; +var FIND_SPACE_RETURN_TAB_RX = /[\n\s\t]+/g; +var FIND_CHAR_TO_TRIM_RX = /^[\u0020\r\n\t]+|[\u0020\r\n\t]+$/g; // find first and last characters for trim + +var FIND_SPACE_MORE_THAN_ONE_RX = /[\u0020]+/g; // find space more than one + +var FIND_CHAR_TO_ESCAPE_RX = /[>(){}[\]+-.!#|]/g; // find characters that need escape + +var FIND_CHAR_TO_ESCAPE_IN_LINK_RX = /[[\]]/g; // find characters to be escaped in links or images + +var FIND_MARKDOWN_IMAGE_SYNTAX_RX = /!\[.*\]\(.*\)/g; // find markdown image syntax + +var TEXT_NODE = 3; +/** + * Iterate properties of object + * from https://github.com/nhnent/fe.code-snippet/blob/master/src/collection.js + * @param {object} obj object to iterate + * @param {function} iteratee callback function + * @param {*} [context] context of callback + */ + +function forEachOwnProperties(obj, iteratee, context) { + var key; + context = context || null; + + for (key in obj) { + if (obj.hasOwnProperty(key)) { + if (iteratee.call(context, obj[key], key, obj) === false) { + break; + } + } + } +} +/** + * Whether if inline node or not + * @param {Node} node Element + * @returns {boolean} + */ +// eslint-disable-next-line complexity + + +function isInlineNode(node) { + var tag = node.tagName; + return tag === 'S' || tag === 'B' || tag === 'I' || tag === 'EM' || tag === 'STRONG' || tag === 'A' || tag === 'IMG' || tag === 'CODE'; +} +/** + * Returns HTML string of an element using given subContent + * @param {Node} node Element + * @param {string} subContent string content of node + * @returns {string} + */ + + +function getRawHtmlString(node, subContent) { + var tempNode = node.cloneNode(false); + tempNode.innerHTML = subContent; + return tempNode.outerHTML; +} +/** + * Clone rules + * @param {object} destination object for apply rules + * @param {object} source source object for clone rules + */ + + +function cloneRules(destination, source) { + forEachOwnProperties(source, function (value, key) { + if (key !== 'converter') { + if (!destination[key]) { + destination[key] = {}; + } + + cloneRules(destination[key], value); + } else { + destination[key] = value; + } + }); +} +/** + * Renderer + * @param {object} [rules] rules to add + * @class + */ + + +var Renderer = /*#__PURE__*/function () { + function Renderer(rules) { + this.rules = {}; + /** + * Line feed replacement text + * @type string + */ + + this.lineFeedReplacement = "\u200B\u200B"; + + if (rules) { + this.addRules(rules); + } + } + /** + * Add rule + * @param {string} selectorString rule selector + * @param {function} converter converter function + */ + + + var _proto = Renderer.prototype; + + _proto.addRule = function addRule(selectorString, converter) { + var selectors = selectorString.split(', '); + var selector = selectors.pop(); + converter.fname = selectorString; + + while (selector) { + this._setConverterWithSelector(selector, converter); + + selector = selectors.pop(); + } + } + /** + * Add rules using object + * @param {object} rules key(rule selector), value(converter function) + */ + ; + + _proto.addRules = function addRules(rules) { + forEachOwnProperties(rules, function (converter, selectorString) { + this.addRule(selectorString, converter); + }, this); + } + /** + * Remove flanked space of dom node + * @param {string} content text content + * @param {HTMLElement} node current node + * @returns {string} result + */ + // eslint-disable-next-line complexity + ; + + _proto.getSpaceControlled = function getSpaceControlled(content, node) { + var lead = ''; + var trail = ''; + var text; + + if (node.previousSibling && (node.previousSibling.nodeType === TEXT_NODE || isInlineNode(node.previousSibling))) { + text = node.previousSibling.innerHTML || node.previousSibling.nodeValue; + + if (FIND_TRAIL_SPACE_RX.test(text) || FIND_LEAD_SPACE_RX.test(node.innerHTML || node.nodeValue)) { + lead = ' '; + } + } + + if (node.nextSibling && (node.nextSibling.nodeType === TEXT_NODE || isInlineNode(node.nextSibling))) { + text = node.nextSibling.innerHTML || node.nextSibling.nodeValue; + + if (FIND_LEAD_SPACE_RX.test(text) || FIND_TRAIL_SPACE_RX.test(node.innerHTML || node.nodeValue)) { + trail = ' '; + } + } + + return lead + content + trail; + } + /** + * Convert dom node to markdown using dom node and subContent + * @param {HTMLElement} node node to convert + * @param {string} subContent child nodes converted text + * @returns {string} converted text + */ + // eslint-disable-next-line complexity + ; + + _proto.convert = function convert(node, subContent) { + var result; + + var converter = this._getConverter(node); + + if (node && node.nodeType === Node.ELEMENT_NODE && node.hasAttribute('data-tomark-pass')) { + node.removeAttribute('data-tomark-pass'); + result = getRawHtmlString(node, subContent); + } else if (converter) { + result = converter.call(this, node, subContent); + } else if (node) { + result = this.getSpaceControlled(this._getInlineHtml(node, subContent), node); + } + + return result || ''; + }; + + _proto._getInlineHtml = function _getInlineHtml(node, subContent) { + var html = node.outerHTML; + var tagName = node.tagName; + var escapedSubContent = subContent.replace(/\$/g, '$$$$'); // escape $: replace all $ char to $$ before we throw this string to replace + + return html.replace(new RegExp("(<" + tagName + " ?.*?>).*()", 'i'), "$1" + escapedSubContent + "$2"); + } + /** + * Get converter function for node + * @private + * @param {HTMLElement} node node + * @returns {function} converter function + */ + ; + + _proto._getConverter = function _getConverter(node) { + var rulePointer = this.rules; + var converter; + + while (node && rulePointer) { + rulePointer = this._getNextRule(rulePointer, this._getRuleNameFromNode(node)); + node = this._getPrevNode(node); + + if (rulePointer && rulePointer.converter) { + converter = rulePointer.converter; + } + } + + return converter; + } + /** + * Get next rule object + * @private + * @param {object} ruleObj rule object + * @param {string} ruleName rule tag name to find + * @returns {object} rule Object + */ + ; + + _proto._getNextRule = function _getNextRule(ruleObj, ruleName) { + return ruleObj[ruleName]; + } + /** + * Get proper rule tag name from node + * @private + * @param {HTMLElement} node node + * @returns {string} rule tag name + */ + ; + + _proto._getRuleNameFromNode = function _getRuleNameFromNode(node) { + return node.tagName || 'TEXT_NODE'; + } + /** + * Get node's available parent node + * @private + * @param {HTMLElement} node node + * @returns {HTMLElement | undefined} result + */ + ; + + _proto._getPrevNode = function _getPrevNode(node) { + var parentNode = node.parentNode; + var previousNode; + + if (parentNode && !parentNode.__htmlRootByToMark) { + previousNode = parentNode; + } + + return previousNode; + } + /** + * Set converter for selector + * @private + * @param {string} selectors rule selector + * @param {function} converter converter function + */ + ; + + _proto._setConverterWithSelector = function _setConverterWithSelector(selectors, converter) { + var rulePointer = this.rules; + + this._eachSelector(selectors, function (ruleElem) { + if (!rulePointer[ruleElem]) { + rulePointer[ruleElem] = {}; + } + + rulePointer = rulePointer[ruleElem]; + }); + + rulePointer.converter = converter; + } + /** + * Iterate each selectors + * @private + * @param {string} selectors rule selectors + * @param {function} iteratee callback + */ + ; + + _proto._eachSelector = function _eachSelector(selectors, iteratee) { + var selectorArray = selectors.split(' '); + var selectorIndex = selectorArray.length - 1; + + while (selectorIndex >= 0) { + iteratee(selectorArray[selectorIndex]); + selectorIndex -= 1; + } + } + /** + * Trim text + * @param {string} text text be trimed + * @returns {string} trimed text + */ + ; + + _proto.trim = function trim(text) { + return text.replace(FIND_CHAR_TO_TRIM_RX, ''); + } + /** + * Returns whether text empty or not + * @param {string} text text be checked + * @returns {boolean} result + */ + ; + + _proto.isEmptyText = function isEmptyText(text) { + return text.replace(FIND_SPACE_RETURN_TAB_RX, '') === ''; + } + /** + * Collape space more than 2 + * @param {string} text text be collapsed + * @returns {string} result + */ + ; + + _proto.getSpaceCollapsedText = function getSpaceCollapsedText(text) { + return text.replace(FIND_SPACE_MORE_THAN_ONE_RX, ' '); + } + /** + * Apply backslash escape to text + * @param {string} text text be processed + * @returns {string} processed text + */ + ; + + _proto.escapeText = function escapeText(text) { + return text.replace(FIND_CHAR_TO_ESCAPE_RX, function (matched) { + return "\\" + matched; + }); + } + /** + * Escape given text for link + * @param {string} text - text be processed + * @returns {string} - processed text + */ + ; + + _proto.escapeTextForLink = function escapeTextForLink(text) { + var imageSyntaxRanges = []; + var result = FIND_MARKDOWN_IMAGE_SYNTAX_RX.exec(text); + + while (result) { + imageSyntaxRanges.push([result.index, result.index + result[0].length]); + result = FIND_MARKDOWN_IMAGE_SYNTAX_RX.exec(text); + } + + return text.replace(FIND_CHAR_TO_ESCAPE_IN_LINK_RX, function (matched, offset) { + var isDelimiter = imageSyntaxRanges.some(function (range) { + return offset > range[0] && offset < range[1]; + }); + return isDelimiter ? matched : "\\" + matched; + }); + } + /** + * Backslash escape to text for html + * Apply backslash escape to text + * @param {string} text text be processed + * @returns {string} processed text + */ + ; + + _proto.escapeTextHtml = function escapeTextHtml(text) { + return text.replace(new RegExp(Renderer.markdownTextToEscapeHtmlRx.source, 'g'), function (matched) { + return "\\" + matched; + }); + } + /** + * Backslash is using for escape ASCII punctuation character. + * https://spec.commonmark.org/0.29/#backslash-escapes + * If user input backslash as text, backslash is kept by inserting backslash. + * For example, if input text is "\$", this text is changed "\\$" + * @param {string} text text be processed + * @returns {string} processed text + */ + ; + + _proto.escapeTextBackSlash = function escapeTextBackSlash(text) { + return text.replace(new RegExp(Renderer.markdownTextToEscapeBackSlashRx.source, 'g'), function (matched) { + return "\\" + matched; + }); + } + /** + * Escapes in markdown paired characters + * @param {string} text Text to escape + * @returns {string} escaped text + */ + ; + + _proto.escapePairedCharacters = function escapePairedCharacters(text) { + return text.replace(new RegExp(Renderer.markdownTextToEscapePairedCharsRx.source, 'g'), function (matched) { + return "\\" + matched; + }); + }; + + _proto._isNeedEscape = function _isNeedEscape(text) { + var res = false; + var markdownTextToEscapeRx = Renderer.markdownTextToEscapeRx; + var type; + + for (type in markdownTextToEscapeRx) { + if (markdownTextToEscapeRx.hasOwnProperty(type) && markdownTextToEscapeRx[type].test(text)) { + res = true; + break; + } + } + + return res; + }; + + _proto._isNeedEscapeHtml = function _isNeedEscapeHtml(text) { + return Renderer.markdownTextToEscapeHtmlRx.test(text); + }; + + _proto._isNeedEscapeBackSlash = function _isNeedEscapeBackSlash(text) { + return Renderer.markdownTextToEscapeBackSlashRx.test(text); + }; + + _proto.mix = function mix(renderer) { + cloneRules(this.rules, renderer.rules); + } + /** + * Renderer factory + * Return new renderer + * @param {Renderer} srcRenderer renderer to extend + * @param {object} rules rule object, key(rule selector), value(converter function) + * @returns {Renderer} renderer + */ + ; + + Renderer.factory = function factory(srcRenderer, rules) { + var renderer = new Renderer(); + + if (!rules) { + rules = srcRenderer; + } else { + renderer.mix(srcRenderer); + } + + renderer.addRules(rules); + return renderer; + }; + + return Renderer; +}(); + +renderer_defineProperty(Renderer, "markdownTextToEscapeRx", { + codeblock: /(^ {4}[^\n]+\n*)+/, + hr: /^ *((\* *){3,}|(- *){3,} *|(_ *){3,}) */, + heading: /^(#{1,6}) +[\s\S]+/, + lheading: /^([^\n]+)\n *(=|-){2,} */, + blockquote: /^( *>[^\n]+.*)+/, + list: /^ *(\*+|-+|\d+\.) [\s\S]+/, + def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? */, + link: /!?\[.*\]\(.*\)/, + reflink: /!?\[.*\]\s*\[([^\]]*)\]/, + verticalBar: /\u007C/, + codeblockGfm: /^(`{3,})/, + codeblockTildes: /^(~{3,})/ +}); + +renderer_defineProperty(Renderer, "markdownTextToEscapeHtmlRx", /<([a-zA-Z_][a-zA-Z0-9\-._]*)(\s|[^\\/>])*\/?>|<(\/)([a-zA-Z_][a-zA-Z0-9\-._]*)\s*\/?>||<([a-zA-Z_][a-zA-Z0-9\-.:/]*)>/); + +renderer_defineProperty(Renderer, "markdownTextToEscapeBackSlashRx", /\\[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~\\]/); + +renderer_defineProperty(Renderer, "markdownTextToEscapePairedCharsRx", /[*_~`]/); + + +// CONCATENATED MODULE: ./src/renderer.basic.js +/** + * @fileoverview Implements basicRenderer + * @author NHN Ent. FE Development Lab + */ + +var FIND_LAST_RETURN_RX = /\n$/g; +var FIND_BR_AND_RETURN_RX = /[ \xA0]+\n\n/g; +var FIND_MULTIPLE_EMPTYLINE_BETWEEN_TEXT_RX = /([ \xA0]+\n){2,}/g; +var FIND_LINK_HREF = /href="(.*?)"/; +var START_OF_LINES_RX = /^/gm; +/** + * Basic Markdown Renderer + * @exports basicRenderer + * @augments Renderer + */ + +/* harmony default export */ var renderer_basic = (Renderer.factory({ + // inlines + TEXT_NODE: function TEXT_NODE(node) { + var managedText = this.trim(this.getSpaceCollapsedText(node.nodeValue)); + + if (this._isNeedEscapeBackSlash(managedText)) { + managedText = this.escapeTextBackSlash(managedText); + } + + managedText = this.escapePairedCharacters(managedText); + + if (this._isNeedEscapeHtml(managedText)) { + managedText = this.escapeTextHtml(managedText); + } + + if (this._isNeedEscape(managedText)) { + managedText = this.escapeText(managedText); + } + + return this.getSpaceControlled(managedText, node); + }, + 'CODE TEXT_NODE': function CODETEXT_NODE(node) { + return node.nodeValue; + }, + 'EM, I': function EMI(node, subContent) { + var res = ''; + + if (!this.isEmptyText(subContent)) { + res = "*" + subContent + "*"; + } + + return res; + }, + 'STRONG, B': function STRONGB(node, subContent) { + var res = ''; + + if (!this.isEmptyText(subContent)) { + res = "**" + subContent + "**"; + } + + return res; + }, + A: function A(node, subContent) { + var res = subContent; + var title = ''; + var url; // "href" attribute is difficult to predict depending on the situation + // so use as it is applied to html + + var foundedHref = FIND_LINK_HREF.exec(node.outerHTML); + + if (foundedHref) { + url = foundedHref[1].replace(/&/g, '&'); + } + + if (node.title) { + title = " \"" + node.title + "\""; + } + + if (!this.isEmptyText(subContent) && url) { + res = "[" + this.escapeTextForLink(subContent) + "](" + url + title + ")"; + } + + return res; + }, + IMG: function IMG(node) { + var src = node.getAttribute('src'); + var alt = node.alt; + + if (src) { + return "![" + this.escapeTextForLink(alt) + "](" + src + ")"; + } + + return ''; + }, + BR: function BR() { + return ' \n'; + }, + CODE: function CODE(node, subContent) { + var backticks, numBackticks; + var res = ''; + + if (!this.isEmptyText(subContent)) { + numBackticks = parseInt(node.getAttribute('data-backticks'), 10); + backticks = isNaN(numBackticks) ? '`' : Array(numBackticks + 1).join('`'); + res = backticks + subContent + backticks; + } + + return res; + }, + // Paragraphs + P: function P(node, subContent) { + var res = ''; // convert multiple brs to one br + + subContent = subContent.replace(FIND_MULTIPLE_EMPTYLINE_BETWEEN_TEXT_RX, ' \n'); + + if (!this.isEmptyText(subContent)) { + res = "\n\n" + subContent + "\n\n"; + } + + return res; + }, + 'BLOCKQUOTE P': function BLOCKQUOTEP(node, subContent) { + return subContent; + }, + 'LI P': function LIP(node, subContent) { + var res = ''; + + if (!this.isEmptyText(subContent)) { + res = subContent; + } + + return res; + }, + // Headings + 'H1, H2, H3, H4, H5, H6': function H1H2H3H4H5H6(node, subContent) { + var res = ''; + var headingNumber = parseInt(node.tagName.charAt(1), 10); + + while (headingNumber) { + res += '#'; + headingNumber -= 1; + } + + res += ' '; + res += subContent; + return "\n\n" + res + "\n\n"; + }, + 'LI H1, LI H2, LI H3, LI H4, LI H5, LI H6': function LIH1LIH2LIH3LIH4LIH5LIH6(node, subContent) { + var headingNumber = parseInt(node.tagName.charAt(1), 10); + return Array(headingNumber + 1).join('#') + " " + subContent; + }, + // List + 'UL, OL': function ULOL(node, subContent) { + return "\n\n" + subContent + "\n\n"; + }, + 'LI OL, LI UL': function LIOLLIUL(node, subContent) { + var processedSubContent; // remove last br of li + + processedSubContent = subContent.replace(FIND_BR_AND_RETURN_RX, '\n'); // parent LI converter add \n too, so we remove last return + + processedSubContent = processedSubContent.replace(FIND_LAST_RETURN_RX, ''); + var res = processedSubContent.replace(START_OF_LINES_RX, ' '); + return "\n" + res; + }, + 'UL LI': function ULLI(node, subContent) { + var res = ''; // convert multiple brs to one br + + subContent = subContent.replace(FIND_MULTIPLE_EMPTYLINE_BETWEEN_TEXT_RX, ' \n'); + + if (node.firstChild && node.firstChild.tagName === 'P') { + res += '\n'; + } + + res += "* " + subContent + "\n"; + return res; + }, + // eslint-disable-next-line complexity + 'OL LI': function OLLI(node, subContent) { + var res = ''; + var liCounter = parseInt(node.parentNode.getAttribute('start') || 1, 10); + + while (node.previousSibling) { + node = node.previousSibling; + + if (node.nodeType === 1 && node.tagName === 'LI') { + liCounter += 1; + } + } // convert multiple brs to one br + + + subContent = subContent.replace(FIND_MULTIPLE_EMPTYLINE_BETWEEN_TEXT_RX, ' \n'); + + if (node.firstChild && node.firstChild.tagName === 'P') { + res += '\n'; + } + + res += liCounter + ". " + subContent + "\n"; + return res; + }, + // HR + HR: function HR() { + return '\n\n- - -\n\n'; + }, + // Blockquote + BLOCKQUOTE: function BLOCKQUOTE(node, subContent) { + // convert multiple brs to one emptyline + subContent = subContent.replace(FIND_MULTIPLE_EMPTYLINE_BETWEEN_TEXT_RX, '\n\n'); + var trimmedText = this.trim(subContent); + var res = trimmedText.replace(START_OF_LINES_RX, '> '); + return "\n\n" + res + "\n\n"; + }, + // Code Block + 'PRE CODE': function PRECODE(node, subContent) { + var lastNremoved = subContent.replace(FIND_LAST_RETURN_RX, ''); + var res = lastNremoved.replace(START_OF_LINES_RX, ' '); + return "\n\n" + res + "\n\n"; + } +})); +// CONCATENATED MODULE: ./src/renderer.gfm.js +/** + * @fileoverview Implements Github flavored markdown renderer + * @author NHN Ent. FE Development Lab + */ + + +/** + * gfmRenderer + * github flavored Markdown Renderer + * + * we didnt render gfm br here because we need distingush returns that made by block with br + * so we render gfm br later in toMark.js finalize function + * @exports gfmRenderer + * @augments Renderer + */ + +/* harmony default export */ var renderer_gfm = (Renderer.factory(renderer_basic, { + 'DEL, S': function DELS(node, subContent) { + return "~~" + subContent + "~~"; + }, + 'PRE CODE': function PRECODE(node, subContent) { + var language = ''; + var numberOfBackticks = node.getAttribute('data-backticks'); + + if (node.getAttribute('data-language')) { + language = " " + node.getAttribute('data-language'); + } + + numberOfBackticks = parseInt(numberOfBackticks, 10); + var backticks = isNaN(numberOfBackticks) ? '```' : Array(numberOfBackticks + 1).join('`'); + subContent = subContent.replace(/(\r\n)|(\r)|(\n)/g, this.lineFeedReplacement); + return "\n\n" + backticks + language + "\n" + subContent + "\n" + backticks + "\n\n"; + }, + PRE: function PRE(node, subContent) { + return subContent; + }, + 'UL LI': function ULLI(node, subContent) { + return renderer_basic.convert(node, makeTaskIfNeed(node, subContent)); + }, + 'OL LI': function OLLI(node, subContent) { + return renderer_basic.convert(node, makeTaskIfNeed(node, subContent)); + }, + // Table + TABLE: function TABLE(node, subContent) { + return "\n\n" + subContent + "\n\n"; + }, + 'TBODY, TFOOT': function TBODYTFOOT(node, subContent) { + return subContent; + }, + 'TR TD, TR TH': function TRTDTRTH(node, subContent) { + subContent = subContent.replace(/(\r\n)|(\r)|(\n)/g, ''); + return " " + subContent + " |"; + }, + 'TD BR, TH BR': function TDBRTHBR() { + return '
      '; + }, + TR: function TR(node, subContent) { + return "|" + subContent + "\n"; + }, + THEAD: function THEAD(node, subContent) { + var result = ''; + var ths = findChildTag(findChildTag(node, 'TR')[0], 'TH'); + + for (var i = 0, thsLength = ths.length; i < thsLength; i += 1) { + result += " " + makeTableHeadAlignText(ths[i]) + " |"; + } + + return subContent ? subContent + "|" + result + "\n" : ''; + } +})); +/** + * Make task Markdown string if need + * @param {HTMLElement} node Passed HTML Element + * @param {string} subContent node's content + * @returns {string} + */ + +function makeTaskIfNeed(node, subContent) { + var condition; + + if (node.className.indexOf('task-list-item') !== -1) { + condition = node.className.indexOf('checked') !== -1 ? 'x' : ' '; + subContent = "[" + condition + "] " + subContent; + } + + return subContent; +} +/** + * Make table head align text + * @param {HTMLElement} th Table head cell element + * @returns {string} + */ + + +function makeTableHeadAlignText(th) { + var leftAlignValue, rightAlignValue, textLength; + var align = th.align; + textLength = th.textContent ? th.textContent.length : th.innerText.length; + leftAlignValue = ''; + rightAlignValue = ''; + + if (align) { + if (align === 'left') { + leftAlignValue = ':'; + textLength -= 1; + } else if (align === 'right') { + rightAlignValue = ':'; + textLength -= 1; + } else if (align === 'center') { + rightAlignValue = ':'; + leftAlignValue = ':'; + textLength -= 2; + } + } + + return leftAlignValue + repeatString('-', textLength) + rightAlignValue; +} +/** + * Find child element of given tag name + * @param {HTMLElement} node starting element + * @param {string} tagName Tag name for search + * @returns {Array.} + */ + + +function findChildTag(node, tagName) { + var childNodes = node.childNodes; + var result = []; + + for (var i = 0, childLength = childNodes.length; i < childLength; i += 1) { + if (childNodes[i].tagName && childNodes[i].tagName === tagName) { + result.push(childNodes[i]); + } + } + + return result; +} +/** + * Repeat given string + * @param {string} pattern String for repeat + * @param {number} count Amount of repeat + * @returns {string} + */ + + +function repeatString(pattern, count) { + var result = pattern; + count = Math.max(count, 3); + + while (count > 1) { + result += pattern; + count -= 1; + } + + return result; +} +// CONCATENATED MODULE: ./src/toMark.js +/** + * @fileoverview Implements toMark + * @author NHN Ent. FE Development Lab + */ + + + + +var FIND_UNUSED_BRS_RX = /[ \xA0]+(\n\n)/g; +var FIND_FIRST_LAST_WITH_SPACE_RETURNS_RX = /^[\n]+|[\s\n]+$/g; +var FIND_MULTIPLE_BRS_RX = /([ \xA0]+\n){2,}/g; +var FIND_RETURNS_RX = /([ \xA0]){2,}\n/g; +var FIND_RETURNS_AND_SPACE_RX = /[ \xA0\n]+/g; +/** + * @exports toMark + * @param {string} htmlStr html string to convert + * @param {object} options option + * @param {boolean} options.gfm if this property is false turn off it cant parse gfm + * @param {Renderer} options.renderer pass renderer to use + * @returns {string} converted markdown text + * @example + * toMark('

      hello world

      '); // "# hello world" + * toMark('strike'); // "~~strike~~" + * toMark('strike', {gfm: false}); // "strike" + */ + +function toMark(htmlStr, options) { + var isGfm = true; + var renderer; + + if (!htmlStr) { + return ''; + } + + renderer = renderer_gfm; + + if (options) { + isGfm = options.gfm; + + if (isGfm === false) { + renderer = renderer_basic; + } + + renderer = options.renderer || renderer; + } + + var runner = new DomRunner(toDom(htmlStr)); + return finalize(parse(runner, renderer), isGfm, renderer.lineFeedReplacement); +} +/** + * Parse dom to markdown + * @param {DomRunner} runner runner + * @param {Renderer} renderer renderer + * @returns {string} markdown text + */ + +function parse(runner, renderer) { + var markdownContent = ''; + + while (runner.next()) { + markdownContent += tracker(runner, renderer); + } + + return markdownContent; +} +/** + * Remove first and last return character + * @param {string} text text to finalize + * @param {boolean} isGfm isGfm flag + * @param {string} lineFeedReplacement Line feed replacement text + * @returns {string} result + */ + + +function finalize(text, isGfm, lineFeedReplacement) { + // collapse return and
      + text = text.replace(FIND_UNUSED_BRS_RX, '\n'); // collapse multiple br + + text = text.replace(FIND_MULTIPLE_BRS_RX, '\n\n'); + text = text.replace(FIND_RETURNS_AND_SPACE_RX, function (matched) { + var returnCount = (matched.match(/\n/g) || []).length; + + if (returnCount >= 3) { + return '\n\n'; + } + + if (matched >= 1) { + return '\n'; + } + + return matched; + }); // remove first and last \n + + text = text.replace(FIND_FIRST_LAST_WITH_SPACE_RETURNS_RX, ''); + text = text.replace(new RegExp(lineFeedReplacement, 'g'), '\n'); // in gfm replace ' \n' make by
      to '\n' + + if (isGfm) { + text = text.replace(FIND_RETURNS_RX, '\n'); + } + + return text; +} +/** + * Iterate childNodes and process conversion using recursive call + * @param {DomRunner} runner dom runner + * @param {Renderer} renderer renderer to use + * @returns {string} processed text + */ + + +function tracker(runner, renderer) { + var subContent = ''; + var node = runner.getNode(); + + for (var i = 0, t = node.childNodes.length; i < t; i += 1) { + runner.next(); + subContent += tracker(runner, renderer); + } + + return renderer.convert(node, subContent); +} +// CONCATENATED MODULE: ./src/index.js +/** + * @fileoverview Implements entry point + * @author NHN Ent. FE Development Lab + */ + + + + +toMark.Renderer = Renderer; +toMark.basicRenderer = renderer_basic; +toMark.gfmRenderer = renderer_gfm; +/* harmony default export */ var src = __webpack_exports__["default"] = (toMark); + +/***/ }) +/******/ ])["default"]; +}); + +/***/ }), +/* 33 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Get HTML element's design classes. + * @author NHN FE Development Lab + */ + + + +var isUndefined = __webpack_require__(8); + +/** + * Get HTML element's design classes. + * @param {(HTMLElement|SVGElement)} element target element + * @returns {string} element css class name + * @memberof module:domUtil + */ +function getClass(element) { + if (!element || !element.className) { + return ''; + } + + if (isUndefined(element.className.baseVal)) { + return element.className; + } + + return element.className.baseVal; +} + +module.exports = getClass; + + +/***/ }), +/* 34 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is a number or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is a number or not. + * If the given variable is a number, return true. + * @param {*} obj - Target for checking + * @returns {boolean} Is number? + * @memberof module:type + */ +function isNumber(obj) { + return typeof obj === 'number' || obj instanceof Number; +} + +module.exports = isNumber; + + +/***/ }), +/* 35 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export CLASS_HIGHLIGHT */ +/* harmony import */ var tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(19); +/* harmony import */ var tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); +/* harmony import */ var tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5); +/* harmony import */ var tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6); +/* harmony import */ var tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(22); +/* harmony import */ var _toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_4__); +/* harmony import */ var _preview__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(38); +/* harmony import */ var _utils_dom__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(0); +/* harmony import */ var _htmlRenderConvertors__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(29); +/* harmony import */ var _scroll_helper__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(18); +/* harmony import */ var _scroll_cache_offsetInfo__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(24); +/* harmony import */ var _utils_markdown__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(2); +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements markdown preview + * @author NHN FE Development Lab + */ + + + + + + + + + + + +var CLASS_HIGHLIGHT = 'te-preview-highlight'; + +function findTableCell(tableRow, _ref) { + var ch = _ref.ch; + var cell = tableRow.firstChild; + + while (cell && cell.next) { + if (Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_10__[/* getMdStartCh */ "e"])(cell.next) > ch + 1) { + break; + } + + cell = cell.next; + } + + return cell; +} +/** + * Class Markdown Preview + * @param {HTMLElement} el - base element + * @param {EventManager} eventManager - event manager + * @param {Convertor} convertor - convertor + * @param {object} options + * @param {boolean} options.isViewer - true for view-only mode + * @param {boolean} options.highlight - true for using live-highlight feature + * @param {object} opitons.linkAttribute - attributes for link element + * @param {object} opitons.customHTMLRenderer - map of custom HTML render functions + + * @ignore + */ + + +var MarkdownPreview = /*#__PURE__*/function (_Preview) { + _inheritsLoose(MarkdownPreview, _Preview); + + function MarkdownPreview(el, eventManager, convertor, options) { + var _this; + + _this = _Preview.call(this, el, eventManager, convertor, options.isViewer) || this; + + _this.lazyRunner.registerLazyRunFunction('invokeCodeBlock', _this.invokeCodeBlockPlugins, _this.delayCodeBlockTime, _assertThisInitialized(_this)); + + var linkAttribute = options.linkAttribute, + customHTMLRenderer = options.customHTMLRenderer, + _options$highlight = options.highlight, + highlight = _options$highlight === void 0 ? false : _options$highlight; + _this.renderHTML = Object(_toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_4__["createRenderHTML"])({ + gfm: true, + nodeId: true, + convertors: Object(_htmlRenderConvertors__WEBPACK_IMPORTED_MODULE_7__[/* getHTMLRenderConvertors */ "a"])(linkAttribute, customHTMLRenderer) + }); + _this.cursorNodeId = null; + + _this._initEvent(highlight); + + return _this; + } + /** + * Initialize event + * @private + */ + + + var _proto = MarkdownPreview.prototype; + + _proto._initEvent = function _initEvent(highlight) { + var _this2 = this; + + this.eventManager.listen('contentChangedFromMarkdown', this.update.bind(this)); // need to implement a listener function for 'previewNeedsRefresh' event + // to support third-party plugins which requires re-executing script for every re-render + + if (highlight) { + this.eventManager.listen('cursorActivity', function (_ref2) { + var markdownNode = _ref2.markdownNode, + cursor = _ref2.cursor; + + _this2._updateCursorNode(markdownNode, cursor); + }); + this.eventManager.listen('blur', function () { + _this2._removeHighlight(); + }); + } + + tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_0___default()(this.el, 'scroll', function (event) { + _this2.eventManager.emit('scroll', { + source: 'preview', + data: Object(_scroll_helper__WEBPACK_IMPORTED_MODULE_8__[/* findAdjacentElementToScrollTop */ "a"])(event.target.scrollTop, _this2._previewContent) + }); + }); + }; + + _proto._removeHighlight = function _removeHighlight() { + if (this.cursorNodeId) { + var currentEl = this._getElementByNodeId(this.cursorNodeId); + + if (currentEl) { + tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_3___default()(currentEl, CLASS_HIGHLIGHT); + } + } + }; + + _proto._updateCursorNode = function _updateCursorNode(cursorNode, cursorPos) { + if (cursorNode) { + cursorNode = Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_10__[/* findClosestNode */ "b"])(cursorNode, function (mdNode) { + return !Object(_utils_markdown__WEBPACK_IMPORTED_MODULE_10__[/* isInlineNode */ "h"])(mdNode); + }); + + if (cursorNode.type === 'tableRow') { + cursorNode = findTableCell(cursorNode, cursorPos); + } else if (cursorNode.type === 'tableBody') { + // empty line next to table + cursorNode = null; + } + } + + var cursorNodeId = cursorNode ? cursorNode.id : null; + + if (this.cursorNodeId === cursorNodeId) { + return; + } + + var inFrontMatter = cursorNode && cursorNode.customType === 'frontMatter'; + + var oldEL = this._getElementByNodeId(this.cursorNodeId); + + var newEL = this._getElementByNodeId(cursorNodeId); + + if (oldEL) { + tui_code_snippet_domUtil_removeClass__WEBPACK_IMPORTED_MODULE_3___default()(oldEL, CLASS_HIGHLIGHT); + } + + if (newEL && !inFrontMatter) { + tui_code_snippet_domUtil_addClass__WEBPACK_IMPORTED_MODULE_2___default()(newEL, CLASS_HIGHLIGHT); + } + + this.cursorNodeId = cursorNodeId; + }; + + _proto._getElementByNodeId = function _getElementByNodeId(nodeId) { + if (!nodeId) { + return null; + } + + return this._previewContent.querySelector("[data-nodeid=\"" + nodeId + "\"]"); + }; + + _proto.update = function update(changed) { + var _this3 = this; + + changed.forEach(function (editResult) { + return _this3.replaceRangeNodes(editResult); + }); + this.eventManager.emit('previewRenderAfter', this); + }; + + _proto.replaceRangeNodes = function replaceRangeNodes(editResult) { + var _this4 = this; + + var nodes = editResult.nodes, + removedNodeRange = editResult.removedNodeRange; + var contentEl = this._previewContent; + var newHtml = this.eventManager.emitReduce('convertorAfterMarkdownToHtmlConverted', nodes.map(function (node) { + return _this4.renderHTML(node); + }).join('')); + + if (!removedNodeRange) { + contentEl.insertAdjacentHTML('afterbegin', newHtml); + } else { + var _removedNodeRange$id = removedNodeRange.id, + startNodeId = _removedNodeRange$id[0], + endNodeId = _removedNodeRange$id[1]; + + var startEl = this._getElementByNodeId(startNodeId); + + var endEl = this._getElementByNodeId(endNodeId); + + if (startEl) { + startEl.insertAdjacentHTML('beforebegin', newHtml); + var el = startEl; + + while (el !== endEl) { + var nextEl = el.nextElementSibling; + el.parentNode.removeChild(el); + Object(_scroll_cache_offsetInfo__WEBPACK_IMPORTED_MODULE_9__[/* removeOffsetInfoByNode */ "c"])(el); + el = nextEl; + } + + if (el.parentNode) { + _utils_dom__WEBPACK_IMPORTED_MODULE_6__[/* default */ "a"].remove(el); + Object(_scroll_cache_offsetInfo__WEBPACK_IMPORTED_MODULE_9__[/* removeOffsetInfoByNode */ "c"])(el); + } + } + } + + var codeBlockEls = this.getCodeBlockElements(nodes.map(function (node) { + return node.id; + })); + + if (codeBlockEls.length) { + this.lazyRunner.run('invokeCodeBlock', codeBlockEls); + } + } + /** + * render + * @param {string} html - html string to render + * @override + */ + ; + + _proto.render = function render(html) { + _Preview.prototype.render.call(this, html); + + this.eventManager.emit('previewRenderAfter', this); + }; + + _proto.remove = function remove() { + tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_1___default()(this.el, 'scroll'); + this.el = null; + }; + + return MarkdownPreview; +}(_preview__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"]); + +/* harmony default export */ __webpack_exports__["a"] = (MarkdownPreview); + +/***/ }), +/* 36 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8); +/* harmony import */ var tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var tui_code_snippet_type_isFalsy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(44); +/* harmony import */ var tui_code_snippet_type_isFalsy__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_type_isFalsy__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var tui_code_snippet_enum_enum__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(45); +/* harmony import */ var tui_code_snippet_enum_enum__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_enum_enum__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _utils_map__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(23); +/** + * @fileoverview Implements EventManager + * @author NHN FE Development Lab + */ + + + + + +var eventList = ['previewBeforeHook', 'previewRenderAfter', 'previewNeedsRefresh', 'addImageBlobHook', 'setMarkdownAfter', 'contentChangedFromWysiwyg', 'changeFromWysiwyg', 'contentChangedFromMarkdown', 'changeFromMarkdown', 'change', 'changeModeToWysiwyg', 'changeModeToMarkdown', 'changeModeBefore', 'changeMode', 'changePreviewStyle', 'changePreviewTabPreview', 'changePreviewTabWrite', 'openPopupAddLink', 'openPopupAddImage', 'openPopupAddTable', 'openPopupTableUtils', 'openHeadingSelect', 'openPopupCodeBlockLanguages', 'openPopupCodeBlockEditor', 'openDropdownToolbar', 'closePopupCodeBlockLanguages', 'closePopupCodeBlockEditor', 'closeAllPopup', 'command', 'addCommandBefore', 'htmlUpdate', 'markdownUpdate', 'renderedHtmlUpdated', 'removeEditor', 'convertorAfterMarkdownToHtmlConverted', 'convertorBeforeHtmlToMarkdownConverted', 'convertorAfterHtmlToMarkdownConverted', 'stateChange', 'wysiwygSetValueAfter', 'wysiwygSetValueBefore', 'wysiwygGetValueBefore', 'wysiwygProcessHTMLText', 'wysiwygRangeChangeAfter', 'wysiwygKeyEvent', 'scroll', 'click', 'mousedown', 'mouseover', 'mouseout', 'mouseup', 'contextmenu', 'keydown', 'keyup', 'keyMap', 'load', 'focus', 'blur', 'paste', 'pasteBefore', 'willPaste', 'copy', 'copyBefore', 'copyAfter', 'cut', 'cutAfter', 'drop', 'show', 'hide', 'changeLanguage', 'cursorActivity', 'requireScrollSync', 'requireScrollIntoView', 'setCodeBlockLanguages']; +/** + * Class EventManager + * @ignore + */ + +var EventManager = /*#__PURE__*/function () { + function EventManager() { + this.events = new _utils_map__WEBPACK_IMPORTED_MODULE_4__[/* default */ "a"](); + this.TYPE = new tui_code_snippet_enum_enum__WEBPACK_IMPORTED_MODULE_3___default.a(eventList); + } + /** + * Listen event and bind event handler + * @param {string} typeStr Event type string + * @param {function} handler Event handler + */ + + + var _proto = EventManager.prototype; + + _proto.listen = function listen(typeStr, handler) { + var typeInfo = this._getTypeInfo(typeStr); + + var eventHandlers = this.events.get(typeInfo.type) || []; + + if (!this._hasEventType(typeInfo.type)) { + throw new Error("There is no event type " + typeInfo.type); + } + + if (typeInfo.namespace) { + handler.namespace = typeInfo.namespace; + } + + eventHandlers.push(handler); + this.events.set(typeInfo.type, eventHandlers); + } + /** + * Emit event + * @param {string} eventName Event name to emit + * @returns {Array} + */ + ; + + _proto.emit = function emit() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var typeStr = args.shift(); + + var typeInfo = this._getTypeInfo(typeStr); + + var eventHandlers = this.events.get(typeInfo.type); + var results; + + if (eventHandlers) { + tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default()(eventHandlers, function (handler) { + var result = handler.apply(void 0, args); + + if (!tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(result)) { + results = results || []; + results.push(result); + } + }); + } + + return results; + } + /** + * Emit given event and return result + * @param {string} eventName Event name to emit + * @param {string} sourceText Source text to change + * @returns {string} + */ + ; + + _proto.emitReduce = function emitReduce() { + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + var type = args.shift(); + var eventHandlers = this.events.get(type); + + if (eventHandlers) { + tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default()(eventHandlers, function (handler) { + var result = handler.apply(void 0, args); + + if (!tui_code_snippet_type_isFalsy__WEBPACK_IMPORTED_MODULE_2___default()(result)) { + args[0] = result; + } + }); + } + + return args[0]; + } + /** + * Get event type and namespace + * @param {string} typeStr Event type name + * @returns {{type: string, namespace: string}} + * @private + */ + ; + + _proto._getTypeInfo = function _getTypeInfo(typeStr) { + var splited = typeStr.split('.'); + return { + type: splited[0], + namespace: splited[1] + }; + } + /** + * Check whether event type exists or not + * @param {string} type Event type name + * @returns {boolean} + * @private + */ + ; + + _proto._hasEventType = function _hasEventType(type) { + return !tui_code_snippet_type_isUndefined__WEBPACK_IMPORTED_MODULE_1___default()(this.TYPE[this._getTypeInfo(type).type]); + } + /** + * Add event type when given event not exists + * @param {string} type Event type name + */ + ; + + _proto.addEventType = function addEventType(type) { + if (this._hasEventType(type)) { + throw new Error("There is already have event type " + type); + } + + this.TYPE.set(type); + } + /** + * Remove event handler from given event type + * @param {string} typeStr Event type name + * @param {function} [handler] - registered event handler + */ + ; + + _proto.removeEventHandler = function removeEventHandler(typeStr, handler) { + var _this = this; + + var _this$_getTypeInfo = this._getTypeInfo(typeStr), + type = _this$_getTypeInfo.type, + namespace = _this$_getTypeInfo.namespace; + + if (type && handler) { + this._removeEventHandlerWithHandler(type, handler); + } else if (type && !namespace) { + // dont use dot notation cuz eslint + this.events.delete(type); + } else if (!type && namespace) { + this.events.forEach(function (eventHandlers, eventType) { + _this._removeEventHandlerWithTypeInfo(eventType, namespace); + }); + } else if (type && namespace) { + this._removeEventHandlerWithTypeInfo(type, namespace); + } + } + /** + * Remove event handler with event handler + * @param {string} type - event type name + * @param {function} handler - event handler + * @private + */ + ; + + _proto._removeEventHandlerWithHandler = function _removeEventHandlerWithHandler(type, handler) { + var eventHandlers = this.events.get(type) || []; + var handlerIndex = eventHandlers.indexOf(handler); + + if (handlerIndex >= 0) { + eventHandlers.splice(handlerIndex, 1); + } + } + /** + * Remove event handler with event type information + * @param {string} type Event type name + * @param {string} namespace Event namespace + * @private + */ + ; + + _proto._removeEventHandlerWithTypeInfo = function _removeEventHandlerWithTypeInfo(type, namespace) { + var handlersToSurvive = []; + var eventHandlers = this.events.get(type); + + if (!eventHandlers) { + return; + } + + eventHandlers.map(function (handler) { + if (handler.namespace !== namespace) { + handlersToSurvive.push(handler); + } + + return null; + }); + this.events.set(type, handlersToSurvive); + }; + + return EventManager; +}(); + +/* harmony default export */ __webpack_exports__["a"] = (EventManager); + +/***/ }), +/* 37 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var _toast_ui_to_mark__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(32); +/* harmony import */ var _toast_ui_to_mark__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_toast_ui_to_mark__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(22); +/* harmony import */ var _toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var _htmlRenderConvertors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); +/* harmony import */ var _utils_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(0); +/** + * @fileoverview Convertor have responsible to convert markdown and html + * @author NHN FE Development Lab + */ + + + + // This regular expression refere markdownIt. +// https://github.com/markdown-it/markdown-it/blob/master/lib/common/html_re.js + +var attrName = '[a-zA-Z_:][a-zA-Z0-9:._-]*'; +var unquoted = '[^"\'=<>`\\x00-\\x20]+'; +var singleQuoted = "'[^']*'"; +var doubleQuoted = '"[^"]*"'; +var attrValue = "(?:" + unquoted + "|" + singleQuoted + "|" + doubleQuoted + ")"; +var attribute = "(?:\\s+" + attrName + "(?:\\s*=\\s*" + attrValue + ")?)*\\s*"; +var openingTag = "(\\\\<|<)([A-Za-z][A-Za-z0-9\\-]*" + attribute + ")(\\/?>)"; +var HTML_TAG_RX = new RegExp(openingTag, 'g'); +var FRONT_MATTER_RX = /^\s?\\-\\-\\-([\s\S]+?)\\-\\-\\-/; +/** + * Class Convertor + * @param {EventManager} em - EventManager instance + * @ignore + */ + +var Convertor = /*#__PURE__*/function () { + function Convertor(em, options) { + if (options === void 0) { + options = {}; + } + + var _options = options, + linkAttribute = _options.linkAttribute, + customHTMLRenderer = _options.customHTMLRenderer, + extendedAutolinks = _options.extendedAutolinks, + referenceDefinition = _options.referenceDefinition, + customParser = _options.customParser, + frontMatter = _options.frontMatter, + customProp = _options.customProp; + this.options = options; + this.mdReader = new _toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_1__["Parser"]({ + extendedAutolinks: extendedAutolinks, + disallowedHtmlBlockTags: ['br'], + referenceDefinition: referenceDefinition, + disallowDeepHeading: true, + customParser: customParser, + frontMatter: frontMatter + }); + this.renderHTML = Object(_toast_ui_toastmark__WEBPACK_IMPORTED_MODULE_1__["createRenderHTML"])({ + gfm: true, + convertors: Object(_htmlRenderConvertors__WEBPACK_IMPORTED_MODULE_2__[/* getHTMLRenderConvertors */ "a"])(linkAttribute, customHTMLRenderer), + customProp: customProp + }); + this.eventManager = em; + } + /** + * _markdownToHtmlWithCodeHighlight + * Convert markdown to html with Codehighlight + * @param {string} markdown markdown text + * @returns {string} html text + * @private + */ + + + var _proto = Convertor.prototype; + + _proto._markdownToHtmlWithCodeHighlight = function _markdownToHtmlWithCodeHighlight(markdown) { + return this.renderHTML(this.mdReader.parse(markdown)); + } + /** + * _markdownToHtml + * Convert markdown to html + * @param {string} markdown markdown text + * @param {object} env environment sandbox for markdownit + * @returns {string} html text + * @private + */ + ; + + _proto._markdownToHtml = function _markdownToHtml(markdown) { + markdown = markdown.replace(HTML_TAG_RX, function (match, $1, $2, $3) { + return match[0] !== '\\' ? "" + $1 + $2 + " data-tomark-pass " + $3 : match; + }); + return this.renderHTML(this.mdReader.parse(markdown)); + } + /** + * Remove BR's data-tomark-pass attribute text when br in code element + * @param {string} renderedHTML Rendered HTML string from markdown editor + * @returns {string} + * @private + */ + ; + + _proto._removeBrToMarkPassAttributeInCode = function _removeBrToMarkPassAttributeInCode(renderedHTML) { + var wrapper = _utils_dom__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"].createElementWith("
      " + renderedHTML + "
      "); + _utils_dom__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"].findAll(wrapper, 'code, pre').forEach(function (codeOrPre) { + var codeEelement = codeOrPre; + codeEelement.innerHTML = codeEelement.innerHTML.replace(/\sdata-tomark-pass\s(\/?)>/g, '$1>'); + }); + renderedHTML = wrapper.innerHTML; + return renderedHTML; + } + /** + * toHTMLWithCodeHighlight + * Convert markdown to html with Codehighlight + * emit convertorAfterMarkdownToHtmlConverted + * @param {string} markdown markdown text + * @returns {string} html text + */ + ; + + _proto.toHTMLWithCodeHighlight = function toHTMLWithCodeHighlight(markdown) { + var html = this._markdownToHtmlWithCodeHighlight(markdown); + + html = this.eventManager.emitReduce('convertorAfterMarkdownToHtmlConverted', html); + return html; + } + /** + * toHTML + * Convert markdown to html + * emit convertorAfterMarkdownToHtmlConverted + * @param {string} markdown markdown text + * @returns {string} html text + */ + ; + + _proto.toHTML = function toHTML(markdown) { + var html = this._markdownToHtml(markdown); + + html = this.eventManager.emitReduce('convertorAfterMarkdownToHtmlConverted', html); + html = this._removeBrToMarkPassAttributeInCode(html); + return html; + }; + + _proto.initHtmlSanitizer = function initHtmlSanitizer(sanitizer) { + this.eventManager.listen('convertorAfterMarkdownToHtmlConverted', function (html) { + return sanitizer(html, true); + }); + } + /** + * toMarkdown + * Convert html to markdown + * emit convertorAfterHtmlToMarkdownConverted + * @param {string} html html text + * @param {object | null} toMarkOptions - toMark library options + * @returns {string} markdown text + */ + ; + + _proto.toMarkdown = function toMarkdown(html, toMarkOptions) { + var result = []; + html = this.eventManager.emitReduce('convertorBeforeHtmlToMarkdownConverted', html); + html = this._appendAttributeForLinkIfNeed(html); + html = this._appendAttributeForBrIfNeed(html); + var markdown = _toast_ui_to_mark__WEBPACK_IMPORTED_MODULE_0___default()(html, toMarkOptions); + + if (this.options.frontMatter) { + markdown = markdown.replace(FRONT_MATTER_RX, '---$1---'); + } + + markdown = this.eventManager.emitReduce('convertorAfterHtmlToMarkdownConverted', markdown); + markdown = this._removeNewlinesBeforeAfterAndBlockElement(markdown); + markdown.split('\n').forEach(function (line, index) { + var FIND_TABLE_RX = /^(
      )+\||\|[^|]*\|/gi; + var FIND_CODE_RX = /`[^`]*
      [^`]*`/gi; + var FIND_BRS_BEFORE_TABLE = /^(
      )+\|/gi; + + if (FIND_TABLE_RX.test(line)) { + line = line.replace(FIND_BRS_BEFORE_TABLE, function (match) { + return match.replace(/
      /gi, '
      \n'); + }); + } else if (!FIND_CODE_RX.test(line)) { + line = line.replace(/
      /gi, '
      \n'); + } + + result[index] = line; + }); + return result.join('\n'); + }; + + _proto._removeNewlinesBeforeAfterAndBlockElement = function _removeNewlinesBeforeAfterAndBlockElement(markdown) { + // Newlines('\n\n') are created on to-mark. + var NEWLINES_BEFORE_BLOCK_RX = /
      \n\n(#{1,6} .*|```|\||(\*+|-+|\d+\.) .*| *>[^\n]+.*)/g; + var NEWLINES_AFTER_BLOCK_RX = /(#{1,6} .*|```|\|)\n\n
      /g; + markdown = markdown.replace(NEWLINES_BEFORE_BLOCK_RX, '
      $1'); + markdown = markdown.replace(NEWLINES_AFTER_BLOCK_RX, '$1\n
      '); + return markdown; + }; + + _proto._appendAttributeForLinkIfNeed = function _appendAttributeForLinkIfNeed(html) { + var LINK_RX = /!?\[.*\]\(<\s*a[^>]*>(.*?)<\s*\/\s*a>\)/gi; + return html.replace(LINK_RX, function (match) { + return match.replace(//gi; + var FIND_DOUBLE_BR_RX = /

      /gi; + var FIND_PASSING_AND_NORMAL_BR_RX = /

      (.)/gi; + var FIRST_TWO_BRS_BEFORE_RX = /([^>]|<\/a>|<\/code>|<\/span>|<\/b>|<\/i>|<\/s>|]*>)/; + var TWO_BRS_RX = /

      /; + var FIND_FIRST_TWO_BRS_RX = new RegExp(FIRST_TWO_BRS_BEFORE_RX.source + TWO_BRS_RX.source, 'g'); + var FIND_ATTRI_WITH_EMTPY_STR_RX = /
      /gi; + html = html.replace(FIND_BR_RX, '
      '); + html = html.replace(FIND_DOUBLE_BR_RX, '

      '); + html = html.replace(FIND_ATTRI_WITH_EMTPY_STR_RX, '
      '); + html = html.replace(FIND_PASSING_AND_NORMAL_BR_RX, '

      $1'); + html = html.replace(FIND_FIRST_TWO_BRS_RX, '$1

      '); // Preserve
      when there is only one empty line before or after a block element. + + html = html.replace(/(.)

      (|
      |
|
    |
      |
      )/g, '$1

      $2'); + html = html.replace(/(<\/h[1-6]>|<\/pre>|<\/table>|<\/ul>|<\/ol>|<\/blockquote>)
      (.)/g, '$1
      $2'); + return html; + }; + + return Convertor; +}(); + +/* harmony default export */ __webpack_exports__["a"] = (Convertor); + +/***/ }), +/* 38 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/domUtil/css.js +var css = __webpack_require__(4); +var css_default = /*#__PURE__*/__webpack_require__.n(css); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/type/isString.js +var isString = __webpack_require__(9); +var isString_default = /*#__PURE__*/__webpack_require__.n(isString); + +// CONCATENATED MODULE: ./src/js/lazyRunner.js +/** + * @fileoverview Implements LazyRunner + * @author NHN FE Development Lab + */ + +/** + * Class LazyRunner + * @ignore + */ + +var lazyRunner_LazyRunner = /*#__PURE__*/function () { + function LazyRunner() { + this.globalTOID = null; + this.lazyRunFunctions = {}; + } + + var _proto = LazyRunner.prototype; + + _proto.run = function run(fn, params, context, delay) { + var TOID; + + if (isString_default()(fn)) { + TOID = this._runRegisteredRun(fn, params, context, delay); + } else { + TOID = this._runSingleRun(fn, params, context, delay, this.globalTOID); + this.globalTOID = TOID; + } + + return TOID; + }; + + _proto.registerLazyRunFunction = function registerLazyRunFunction(name, fn, delay, context) { + context = context || this; + this.lazyRunFunctions[name] = { + fn: fn, + delay: delay, + context: context, + TOID: null + }; + }; + + _proto._runSingleRun = function _runSingleRun(fn, params, context, delay, TOID) { + this._clearTOIDIfNeed(TOID); + + TOID = setTimeout(function () { + fn.call(context, params); + }, delay); + return TOID; + }; + + _proto._runRegisteredRun = function _runRegisteredRun(lazyRunName, params, context, delay) { + var lazyRunFunction = this.lazyRunFunctions[lazyRunName]; + var fn = lazyRunFunction.fn; + var TOID = lazyRunFunction.TOID; + delay = delay || lazyRunFunction.delay; + context = context || lazyRunFunction.context; + TOID = this._runSingleRun(fn, params, context, delay, TOID); + lazyRunFunction.TOID = TOID; + return TOID; + }; + + _proto._clearTOIDIfNeed = function _clearTOIDIfNeed(TOID) { + if (TOID) { + clearTimeout(TOID); + } + }; + + return LazyRunner; +}(); + +/* harmony default export */ var lazyRunner = (lazyRunner_LazyRunner); +// EXTERNAL MODULE: ./src/js/utils/dom.js +var dom = __webpack_require__(0); + +// EXTERNAL MODULE: ./src/js/codeBlockManager.js +var codeBlockManager = __webpack_require__(30); + +// CONCATENATED MODULE: ./src/js/preview.js +/** + * @fileoverview Implements preview + * @author NHN FE Development Lab + */ + + + + +/** + * Class Preview + * @param {HTMLElement} el - Container element for preview + * @param {EventManager} eventManager - Event manager instance + * @param {Convertor} convertor - Convertor instance + * @param {boolean} isViewer - whether viewer mode or not + * @ignore + */ + +var preview_Preview = /*#__PURE__*/function () { + function Preview(el, eventManager, convertor, isViewer) { + this.eventManager = eventManager; + this.convertor = convertor; + this.el = el; + this.isViewer = !!isViewer; + this.delayCodeBlockTime = 500; + + this._initContentSection(); + + this.lazyRunner = new lazyRunner(); + } + /** + * Initialize content selection + * @private + */ + + + var _proto = Preview.prototype; + + _proto._initContentSection = function _initContentSection() { + this._previewContent = dom["a" /* default */].createElementWith("
      "); + this.el.appendChild(this._previewContent); + }; + + _proto.getCodeBlockElements = function getCodeBlockElements(nodeIds) { + var contentEl = this._previewContent; + var codeEls = []; + var targetEls; + + if (nodeIds) { + targetEls = nodeIds.map(function (id) { + return contentEl.querySelector("[data-nodeid=\"" + id + "\"]"); + }).filter(Boolean); + } else { + targetEls = [contentEl]; + } + + targetEls.forEach(function (targetEl) { + codeEls.push.apply(codeEls, dom["a" /* default */].findAll(targetEl, 'code[data-language]')); + }); + return codeEls; + }; + + _proto.invokeCodeBlockPlugins = function invokeCodeBlockPlugins(codeBlocks) { + codeBlocks.forEach(function (codeBlock) { + var lang = codeBlock.getAttribute('data-language'); + var html = codeBlockManager["a" /* default */].createCodeBlockHtml(lang, codeBlock.textContent); + codeBlock.innerHTML = html; + }); + } + /** + * Refresh rendering + * @param {string} markdown Markdown text + */ + ; + + _proto.refresh = function refresh(markdown) { + if (markdown === void 0) { + markdown = ''; + } + + this.render(this.convertor.toHTMLWithCodeHighlight(markdown)); + this.invokeCodeBlockPlugins(this.getCodeBlockElements()); + } + /** + * get html string + * @returns {string} - html preview string + */ + ; + + _proto.getHTML = function getHTML() { + return this._previewContent.innerHTML; + } + /** + * set html string + * @param {string} html - html preview string + */ + ; + + _proto.setHTML = function setHTML(html) { + this._previewContent.innerHTML = html; + } + /** + * Render HTML on preview + * @param {string} html HTML string + */ + ; + + _proto.render = function render(html) { + var _previewContent = this._previewContent; + html = this.eventManager.emit('previewBeforeHook', html) || html; + dom["a" /* default */].empty(_previewContent); + _previewContent.innerHTML = html; + } + /** + * Set preview height + * @param {number} height - Height for preview container + */ + ; + + _proto.setHeight = function setHeight(height) { + css_default()(this.el, { + height: height + "px" + }); + } + /** + * set min height + * @param {number} minHeight - min height + */ + ; + + _proto.setMinHeight = function setMinHeight(minHeight) { + css_default()(this.el, { + minHeight: minHeight + "px" + }); + } + /** + * Is Preview visible + * @returns {boolean} result + */ + ; + + _proto.isVisible = function isVisible() { + return this.el.style.display !== 'none'; + }; + + return Preview; +}(); + +/* harmony default export */ var preview = __webpack_exports__["a"] = (preview_Preview); + +/***/ }), +/* 39 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Set className value + * @author NHN FE Development Lab + */ + + + +var isArray = __webpack_require__(17); +var isUndefined = __webpack_require__(8); + +/** + * Set className value + * @param {(HTMLElement|SVGElement)} element - target element + * @param {(string|string[])} cssClass - class names + * @private + */ +function setClassName(element, cssClass) { + cssClass = isArray(cssClass) ? cssClass.join(' ') : cssClass; + + cssClass = cssClass.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + + if (isUndefined(element.className.baseVal)) { + element.className = cssClass; + + return; + } + + element.className.baseVal = cssClass; +} + +module.exports = setClassName; + + +/***/ }), +/* 40 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Get event collection for specific HTML element + * @author NHN FE Development Lab + */ + + + +var EVENT_KEY = '_feEventKey'; + +/** + * Get event collection for specific HTML element + * @param {HTMLElement} element - HTML element + * @param {string} type - event type + * @returns {array} + * @private + */ +function safeEvent(element, type) { + var events = element[EVENT_KEY]; + var handlers; + + if (!events) { + events = element[EVENT_KEY] = {}; + } + + handlers = events[type]; + if (!handlers) { + handlers = events[type] = []; + } + + return handlers; +} + +module.exports = safeEvent; + + +/***/ }), +/* 41 */ +/***/ (function(module, exports, __webpack_require__) { + +// extracted by mini-css-extract-plugin + +/***/ }), +/* 42 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is truthy or not. + * @author NHN FE Development Lab + */ + + + +var isExisty = __webpack_require__(28); + +/** + * Check whether the given variable is truthy or not. + * If the given variable is not null or not undefined or not false, returns true. + * (It regards 0 as true) + * @param {*} obj - Target for checking + * @returns {boolean} Is truthy? + * @memberof module:type + */ +function isTruthy(obj) { + return isExisty(obj) && obj !== false; +} + +module.exports = isTruthy; + + +/***/ }), +/* 43 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Send hostname on DOMContentLoaded. + * @author NHN FE Development Lab + */ + + + +var isUndefined = __webpack_require__(8); +var imagePing = __webpack_require__(49); + +var ms7days = 7 * 24 * 60 * 60 * 1000; + +/** + * Check if the date has passed 7 days + * @param {number} date - milliseconds + * @returns {boolean} + * @private + */ +function isExpired(date) { + var now = new Date().getTime(); + + return now - date > ms7days; +} + +/** + * Send hostname on DOMContentLoaded. + * To prevent hostname set tui.usageStatistics to false. + * @param {string} appName - application name + * @param {string} trackingId - GA tracking ID + * @ignore + */ +function sendHostname(appName, trackingId) { + var url = 'https://www.google-analytics.com/collect'; + var hostname = location.hostname; + var hitType = 'event'; + var eventCategory = 'use'; + var applicationKeyForStorage = 'TOAST UI ' + appName + ' for ' + hostname + ': Statistics'; + var date = window.localStorage.getItem(applicationKeyForStorage); + + // skip if the flag is defined and is set to false explicitly + if (!isUndefined(window.tui) && window.tui.usageStatistics === false) { + return; + } + + // skip if not pass seven days old + if (date && !isExpired(date)) { + return; + } + + window.localStorage.setItem(applicationKeyForStorage, new Date().getTime()); + + setTimeout(function() { + if (document.readyState === 'interactive' || document.readyState === 'complete') { + imagePing(url, { + v: 1, + t: hitType, + tid: trackingId, + cid: hostname, + dp: hostname, + dh: appName, + el: appName, + ec: eventCategory + }); + } + }, 1000); +} + +module.exports = sendHostname; + + +/***/ }), +/* 44 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is falsy or not. + * @author NHN FE Development Lab + */ + + + +var isTruthy = __webpack_require__(42); + +/** + * Check whether the given variable is falsy or not. + * If the given variable is null or undefined or false, returns true. + * @param {*} obj - Target for checking + * @returns {boolean} Is falsy? + * @memberof module:type + */ +function isFalsy(obj) { + return !isTruthy(obj); +} + +module.exports = isFalsy; + + +/***/ }), +/* 45 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview This module provides a Enum Constructor. + * @author NHN FE Development Lab + * @example + * // node, commonjs + * var Enum = require('tui-code-snippet/enum/enum'); + */ + + + +var isNumber = __webpack_require__(34); +var isArray = __webpack_require__(17); +var toArray = __webpack_require__(3); +var forEach = __webpack_require__(26); + +/** + * Check whether the defineProperty() method is supported. + * @type {boolean} + * @ignore + */ +var isSupportDefinedProperty = (function() { + try { + Object.defineProperty({}, 'x', {}); + + return true; + } catch (e) { + return false; + } +})(); + +/** + * A unique value of a constant. + * @type {number} + * @ignore + */ +var enumValue = 0; + +/** + * Make a constant-list that has unique values. + * In modern browsers (except IE8 and lower), + * a value defined once can not be changed. + * + * @param {...string|string[]} itemList Constant-list (An array of string is available) + * @class + * + * @example + * var Enum = require('tui-code-snippet/enum/enum'); // node, commonjs + * + * var MYENUM = new Enum('TYPE1', 'TYPE2'); + * var MYENUM2 = new Enum(['TYPE1', 'TYPE2']); + * + * //usage + * if (value === MYENUM.TYPE1) { + * .... + * } + * + * //add (If a duplicate name is inputted, will be disregarded.) + * MYENUM.set('TYPE3', 'TYPE4'); + * + * //get name of a constant by a value + * MYENUM.getName(MYENUM.TYPE1); // 'TYPE1' + * + * // In modern browsers (except IE8 and lower), a value can not be changed in constants. + * var originalValue = MYENUM.TYPE1; + * MYENUM.TYPE1 = 1234; // maybe TypeError + * MYENUM.TYPE1 === originalValue; // true + **/ +function Enum(itemList) { + if (itemList) { + this.set.apply(this, arguments); + } +} + +/** + * Define a constants-list + * @param {...string|string[]} itemList Constant-list (An array of string is available) + */ +Enum.prototype.set = function(itemList) { + var self = this; + + if (!isArray(itemList)) { + itemList = toArray(arguments); + } + + forEach(itemList, function itemListIteratee(item) { + self._addItem(item); + }); +}; + +/** + * Return a key of the constant. + * @param {number} value A value of the constant. + * @returns {string|undefined} Key of the constant. + */ +Enum.prototype.getName = function(value) { + var self = this; + var foundedKey; + + forEach(this, function(itemValue, key) { // eslint-disable-line consistent-return + if (self._isEnumItem(key) && value === itemValue) { + foundedKey = key; + + return false; + } + }); + + return foundedKey; +}; + +/** + * Create a constant. + * @private + * @param {string} name Constant name. (It will be a key of a constant) + */ +Enum.prototype._addItem = function(name) { + var value; + + if (!this.hasOwnProperty(name)) { + value = this._makeEnumValue(); + + if (isSupportDefinedProperty) { + Object.defineProperty(this, name, { + enumerable: true, + configurable: false, + writable: false, + value: value + }); + } else { + this[name] = value; + } + } +}; + +/** + * Return a unique value for assigning to a constant. + * @private + * @returns {number} A unique value + */ +Enum.prototype._makeEnumValue = function() { + var value; + + value = enumValue; + enumValue += 1; + + return value; +}; + +/** + * Return whether a constant from the given key is in instance or not. + * @param {string} key - A constant key + * @returns {boolean} Result + * @private + */ +Enum.prototype._isEnumItem = function(key) { + return isNumber(this[key]); +}; + +module.exports = Enum; + + +/***/ }), +/* 46 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var tui_code_snippet_object_extend__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7); +/* harmony import */ var tui_code_snippet_object_extend__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_object_extend__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(19); +/* harmony import */ var tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(20); +/* harmony import */ var tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _mdPreview__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(35); +/* harmony import */ var _eventManager__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(36); +/* harmony import */ var _commandManager__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1); +/* harmony import */ var _convertor__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(37); +/* harmony import */ var _utils_dom__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(0); +/* harmony import */ var _codeBlockManager__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(30); +/* harmony import */ var _pluginHelper__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(31); +/* harmony import */ var _utils_common__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(12); +/* harmony import */ var _htmlSanitizer__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(25); +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +/** + * @fileoverview Implements editor preivew + * @author NHN FE Development Lab + */ + + + + + + + + + + + + + +var TASK_ATTR_NAME = 'data-te-task'; +var DISABLED_TASK_ATTR_NAME = 'data-te-task-disabled'; +var TASK_CHECKED_CLASS_NAME = 'checked'; +/** + * Class ToastUIEditorViewer + * @param {object} options Option object + * @param {HTMLElement} options.el - container element + * @param {string} [options.initialValue] Editor's initial value + * @param {Object} [options.events] - Events + * @param {function} [options.events.load] - It would be emitted when editor fully load + * @param {function} [options.events.change] - It would be emitted when content changed + * @param {function} [options.events.stateChange] - It would be emitted when format change by cursor position + * @param {function} [options.events.focus] - It would be emitted when editor get focus + * @param {function} [options.events.blur] - It would be emitted when editor loose focus + * @param {Object} [options.hooks] - Hooks + * @param {function} [options.hooks.previewBeforeHook] - Submit preview to hook URL before preview be shown + * @param {Array.} [options.plugins] - Array of plugins. A plugin can be either a function or an array in the form of [function, options]. + * @param {boolean} [options.useDefaultHTMLSanitizer=true] - use default htmlSanitizer + * @param {Object} [options.extendedAutolinks] - Using extended Autolinks specified in GFM spec + * @param {Object} [options.customConvertor] - convertor extention + * @param {Object} [options.linkAttribute] - Attributes of anchor element that should be rel, target, contenteditable, hreflang, type + * @param {Object} [options.customHTMLRenderer] - Object containing custom renderer functions correspond to markdown node + * @param {boolean} [options.referenceDefinition=false] - whether use the specification of link reference definition + * @param {function} [options.customHTMLSanitizer=null] - custom HTML sanitizer + * @param {boolean} [options.frontMatter=false] - whether use the front matter + */ + +var ToastUIEditorViewer = /*#__PURE__*/function () { + function ToastUIEditorViewer(options) { + var _this = this; + + this.options = tui_code_snippet_object_extend__WEBPACK_IMPORTED_MODULE_1___default()({ + useDefaultHTMLSanitizer: true, + linkAttribute: null, + extendedAutolinks: false, + customConvertor: null, + customHTMLRenderer: null, + referenceDefinition: false, + customHTMLSanitizer: null, + frontMatter: false + }, options); + this.codeBlockLanguages = []; + this.eventManager = new _eventManager__WEBPACK_IMPORTED_MODULE_5__[/* default */ "a"](); + this.commandManager = new _commandManager__WEBPACK_IMPORTED_MODULE_6__[/* default */ "a"](this); + var linkAttribute = Object(_utils_common__WEBPACK_IMPORTED_MODULE_11__[/* sanitizeLinkAttribute */ "c"])(this.options.linkAttribute); + + var _getPluginInfo = Object(_pluginHelper__WEBPACK_IMPORTED_MODULE_10__[/* getPluginInfo */ "a"])(this.options.plugins), + renderer = _getPluginInfo.renderer, + parser = _getPluginInfo.parser, + plugins = _getPluginInfo.plugins; + + var _this$options = this.options, + customHTMLRenderer = _this$options.customHTMLRenderer, + customHTMLSanitizer = _this$options.customHTMLSanitizer, + extendedAutolinks = _this$options.extendedAutolinks, + referenceDefinition = _this$options.referenceDefinition, + frontMatter = _this$options.frontMatter; + var rendererOptions = { + linkAttribute: linkAttribute, + customHTMLRenderer: _extends({}, renderer, customHTMLRenderer), + extendedAutolinks: extendedAutolinks, + referenceDefinition: referenceDefinition, + customParser: parser, + frontMatter: frontMatter + }; + + if (this.options.customConvertor) { + // eslint-disable-next-line new-cap + this.convertor = new this.options.customConvertor(this.eventManager, rendererOptions); + } else { + this.convertor = new _convertor__WEBPACK_IMPORTED_MODULE_7__[/* default */ "a"](this.eventManager, rendererOptions); + } + + var sanitizer = customHTMLSanitizer || (this.options.useDefaultHTMLSanitizer ? _htmlSanitizer__WEBPACK_IMPORTED_MODULE_12__[/* default */ "a"] : null); + + if (sanitizer) { + this.convertor.initHtmlSanitizer(sanitizer); + } + + if (this.options.hooks) { + tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default()(this.options.hooks, function (fn, key) { + _this.addHook(key, fn); + }); + } + + if (this.options.events) { + tui_code_snippet_collection_forEachOwnProperties__WEBPACK_IMPORTED_MODULE_0___default()(this.options.events, function (fn, key) { + _this.on(key, fn); + }); + } + + var _this$options2 = this.options, + el = _this$options2.el, + initialValue = _this$options2.initialValue; + var existingHTML = el.innerHTML; + el.innerHTML = ''; + this.preview = new _mdPreview__WEBPACK_IMPORTED_MODULE_4__[/* default */ "a"](el, this.eventManager, this.convertor, _extends({}, rendererOptions, { + isViewer: true + })); + tui_code_snippet_domEvent_on__WEBPACK_IMPORTED_MODULE_2___default()(this.preview.el, 'mousedown', this._toggleTask.bind(this)); + + if (plugins) { + Object(_pluginHelper__WEBPACK_IMPORTED_MODULE_10__[/* invokePlugins */ "b"])(plugins, this); + } + + if (initialValue) { + this.setMarkdown(initialValue); + } else if (existingHTML) { + this.preview.setHTML(existingHTML); + } + + this.eventManager.emit('load', this); + } + /** + * Toggle task by detecting mousedown event. + * @param {MouseEvent} ev - event + * @private + */ + + + var _proto = ToastUIEditorViewer.prototype; + + _proto._toggleTask = function _toggleTask(ev) { + var style = getComputedStyle(ev.target, ':before'); + + if (!ev.target.hasAttribute(DISABLED_TASK_ATTR_NAME) && ev.target.hasAttribute(TASK_ATTR_NAME) && _utils_dom__WEBPACK_IMPORTED_MODULE_8__[/* default */ "a"].isInsideButtonBox(style, ev.offsetX, ev.offsetY)) { + _utils_dom__WEBPACK_IMPORTED_MODULE_8__[/* default */ "a"].toggleClass(ev.target, TASK_CHECKED_CLASS_NAME); + this.eventManager.emit('change', { + source: 'viewer', + data: ev + }); + } + } + /** + * Set content for preview + * @param {string} markdown Markdown text + */ + ; + + _proto.setMarkdown = function setMarkdown(markdown) { + this.markdownValue = markdown = markdown || ''; + this.preview.refresh(this.markdownValue); + this.eventManager.emit('setMarkdownAfter', this.markdownValue); + } + /** + * Bind eventHandler to event type + * @param {string} type Event type + * @param {function} handler Event handler + */ + ; + + _proto.on = function on(type, handler) { + this.eventManager.listen(type, handler); + } + /** + * Unbind eventHandler from event type + * @param {string} type Event type + */ + ; + + _proto.off = function off(type) { + this.eventManager.removeEventHandler(type); + } + /** + * Remove Viewer preview from document + */ + ; + + _proto.remove = function remove() { + this.eventManager.emit('removeEditor'); + tui_code_snippet_domEvent_off__WEBPACK_IMPORTED_MODULE_3___default()(this.preview.el, 'mousedown', this._toggleTask.bind(this)); + this.preview.remove(); + this.options = null; + this.eventManager = null; + this.commandManager = null; + this.convertor = null; + this.preview = null; + } + /** + * Add hook to Viewer preview's event + * @param {string} type Event type + * @param {function} handler Event handler + */ + ; + + _proto.addHook = function addHook(type, handler) { + this.eventManager.removeEventHandler(type); + this.eventManager.listen(type, handler); + } + /** + * Return true + * @returns {boolean} + */ + ; + + _proto.isViewer = function isViewer() { + return true; + } + /** + * Return false + * @returns {boolean} + */ + ; + + _proto.isMarkdownMode = function isMarkdownMode() { + return false; + } + /** + * Return false + * @returns {boolean} + */ + ; + + _proto.isWysiwygMode = function isWysiwygMode() { + return false; + } + /** + * Set code block languages + * @param {Array} languages - code lauguage list + */ + ; + + _proto.setCodeBlockLanguages = function setCodeBlockLanguages(languages) { + var _this2 = this; + + if (languages === void 0) { + languages = []; + } + + languages.forEach(function (lang) { + if (_this2.codeBlockLanguages.indexOf(lang) < 0) { + _this2.codeBlockLanguages.push(lang); + } + }); + }; + + return ToastUIEditorViewer; +}(); +/** + * Check whether is viewer (using in plugins) + * @type {boolean} + * @ignore + */ + + +ToastUIEditorViewer.isViewer = true; +/** + * domUtil instance + * @type {DomUtil} + * @ignore + */ + +ToastUIEditorViewer.domUtils = _utils_dom__WEBPACK_IMPORTED_MODULE_8__[/* default */ "a"]; +/** + * CodeBlockManager instance using in plugins + * @type {CodeBlockManager} + * @ignore + */ + +ToastUIEditorViewer.codeBlockManager = _codeBlockManager__WEBPACK_IMPORTED_MODULE_9__[/* default */ "a"]; +/** + * WwCodeBlockManager class using in plugins + * @type {Class.} + * @ignore + */ + +ToastUIEditorViewer.WwCodeBlockManager = null; +/** + * WwTableManager class using in plugins + * @type {Class.} + * @ignore + */ + +ToastUIEditorViewer.WwTableManager = null; +/** + * WwTableManager class using in plugins + * @type {Class.} + * @ignore + */ + +ToastUIEditorViewer.WwTableSelectionManager = null; +/* harmony default export */ __webpack_exports__["a"] = (ToastUIEditorViewer); + +/***/ }), +/* 47 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Creates a debounced function that delays invoking fn until after delay milliseconds has elapsed since the last time the debouced function was invoked. + * @author NHN FE Development Lab + */ + + + +/** + * @module tricks + */ + +/** + * Creates a debounced function that delays invoking fn until after delay milliseconds has elapsed + * since the last time the debouced function was invoked. + * @param {function} fn The function to debounce. + * @param {number} [delay=0] The number of milliseconds to delay + * @returns {function} debounced function. + * @memberof module:tricks + * @example + * var debounce = require('tui-code-snippet/tricks/debounce'); // node, commonjs + * + * function someMethodToInvokeDebounced() {} + * + * var debounced = debounce(someMethodToInvokeDebounced, 300); + * + * // invoke repeatedly + * debounced(); + * debounced(); + * debounced(); + * debounced(); + * debounced(); + * debounced(); // last invoke of debounced() + * + * // invoke someMethodToInvokeDebounced() after 300 milliseconds. + */ +function debounce(fn, delay) { + var timer, args; + + /* istanbul ignore next */ + delay = delay || 0; + + function debounced() { // eslint-disable-line require-jsdoc + args = Array.prototype.slice.call(arguments); + + window.clearTimeout(timer); + timer = window.setTimeout(function() { + fn.apply(null, args); + }, delay); + } + + return debounced; +} + +module.exports = debounce; + + +/***/ }), +/* 48 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is null or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is null or not. + * If the given variable(arguments[0]) is null, returns true. + * @param {*} obj - Target for checking + * @returns {boolean} Is null? + * @memberof module:type + */ +function isNull(obj) { + return obj === null; +} + +module.exports = isNull; + + +/***/ }), +/* 49 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Request image ping. + * @author NHN FE Development Lab + */ + + + +var forEachOwnProperties = __webpack_require__(10); + +/** + * @module request + */ + +/** + * Request image ping. + * @param {String} url url for ping request + * @param {Object} trackingInfo infos for make query string + * @returns {HTMLElement} + * @memberof module:request + * @example + * var imagePing = require('tui-code-snippet/request/imagePing'); // node, commonjs + * + * imagePing('https://www.google-analytics.com/collect', { + * v: 1, + * t: 'event', + * tid: 'trackingid', + * cid: 'cid', + * dp: 'dp', + * dh: 'dh' + * }); + */ +function imagePing(url, trackingInfo) { + var trackingElement = document.createElement('img'); + var queryString = ''; + forEachOwnProperties(trackingInfo, function(value, key) { + queryString += '&' + key + '=' + value; + }); + queryString = queryString.substring(1); + + trackingElement.src = url + '?' + queryString; + + trackingElement.style.display = 'none'; + document.body.appendChild(trackingElement); + document.body.removeChild(trackingElement); + + return trackingElement; +} + +module.exports = imagePing; + + +/***/ }), +/* 50 */ +/***/ (function(module, exports, __webpack_require__) { + +// extracted by mini-css-extract-plugin + +/***/ }), +/* 51 */ +/***/ (function(module, exports, __webpack_require__) { + +// extracted by mini-css-extract-plugin + +/***/ }), +/* 52 */ +/***/ (function(module, exports, __webpack_require__) { + +// extracted by mini-css-extract-plugin + +/***/ }), +/* 53 */, +/* 54 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is an object or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is an object or not. + * If the given variable is an object, return true. + * @param {*} obj - Target for checking + * @returns {boolean} Is object? + * @memberof module:type + */ +function isObject(obj) { + return obj === Object(obj); +} + +module.exports = isObject; + + +/***/ }), +/* 55 */ +/***/ (function(module, exports, __webpack_require__) { + +!function(e,t){"use strict";function n(e,t,n){this.root=this.currentNode=e,this.nodeType=t,this.filter=n||ue}function o(e,t){for(var n=e.length;n--;)if(!t(e[n]))return!1;return!0}function i(e){return e.nodeType===M&&!!pe[e.nodeName]}function r(e){switch(e.nodeType){case H:return me;case M:case z:if(de&&Ne.has(e))return Ne.get(e);break;default:return ge}var t;return t=o(e.childNodes,a)?fe.test(e.nodeName)?me:ve:Ce,de&&Ne.set(e,t),t}function a(e){return r(e)===me}function s(e){return r(e)===ve}function d(e){return r(e)===Ce}function l(e,t){var o=new n(t,q,s);return o.currentNode=e,o}function c(e,t){return e=l(e,t).previousNode(),e!==t?e:null}function h(e,t){return e=l(e,t).nextNode(),e!==t?e:null}function u(e){return!e.textContent&&!e.querySelector("IMG")}function f(e,t){return!i(e)&&e.nodeType===t.nodeType&&e.nodeName===t.nodeName&&"A"!==e.nodeName&&e.className===t.className&&(!e.style&&!t.style||e.style.cssText===t.style.cssText)}function p(e,t,n){if(e.nodeName!==t)return!1;for(var o in n)if(e.getAttribute(o)!==n[o])return!1;return!0}function g(e,t,n,o){for(;e&&e!==t;){if(p(e,n,o))return e;e=e.parentNode}return null}function m(e,t,n){for(;e&&e!==t;){if(n.test(e.nodeName))return e;e=e.parentNode}return null}function v(e,t){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function C(e,t,n){var o,i,r,a,s,d="";return e&&e!==t&&(d=C(e.parentNode,t,n),e.nodeType===M&&(d+=(d?">":"")+e.nodeName,(o=e.id)&&(d+="#"+o),(i=e.className.trim())&&(r=i.split(/\s\s*/),r.sort(),d+=".",d+=r.join(".")),(a=e.dir)&&(d+="[dir="+a+"]"),r&&(s=n.classNames,ce.call(r,s.highlight)>-1&&(d+="[backgroundColor="+e.style.backgroundColor.replace(/ /g,"")+"]"),ce.call(r,s.colour)>-1&&(d+="[color="+e.style.color.replace(/ /g,"")+"]"),ce.call(r,s.fontFamily)>-1&&(d+="[fontFamily="+e.style.fontFamily.replace(/ /g,"")+"]"),ce.call(r,s.fontSize)>-1&&(d+="[fontSize="+e.style.fontSize+"]")))),d}function N(e){var t=e.nodeType;return t===M||t===z?e.childNodes.length:e.length||0}function _(e){var t=e.parentNode;return t&&t.removeChild(e),e}function S(e,t){var n=e.parentNode;n&&n.replaceChild(t,e)}function y(e){for(var t=e.ownerDocument.createDocumentFragment(),n=e.childNodes,o=n?n.length:0;o--;)t.appendChild(e.firstChild);return t}function T(e,n,o,i){var r,a,s,d=e.createElement(n);if(o instanceof Array&&(i=o,o=null),o)for(r in o)o[r]!==t&&d.setAttribute(r,o[r]);if(i)for(a=0,s=i.length;as?t.startOffset-=1:t.startOffset===s&&(t.startContainer=o,t.startOffset=N(o))),t.endContainer===e&&(t.endOffset>s?t.endOffset-=1:t.endOffset===s&&(t.endContainer=o,t.endOffset=N(o))),_(n),n.nodeType===H?o.appendData(n.data):d.push(y(n));else if(n.nodeType===M){for(i=d.length;i--;)n.appendChild(d.pop());x(n,t)}}function A(e,t){if(e.nodeType===H&&(e=e.parentNode),e.nodeType===M){var n={startContainer:t.startContainer,startOffset:t.startOffset,endContainer:t.endContainer,endOffset:t.endOffset};x(e,n),t.setStart(n.startContainer,n.startOffset),t.setEnd(n.endContainer,n.endOffset)}}function L(e){var t=e.nodeName;return"TD"===t||"TH"===t||"TR"===t||"TBODY"===t||"THEAD"===t}function B(e,t,n,o){var i,r,a,s=t;if(!L(e)||!L(t)){for(;(i=s.parentNode)&&i!==o&&i.nodeType===M&&1===i.childNodes.length;)s=i;_(s),a=e.childNodes.length,r=e.lastChild,r&&"BR"===r.nodeName&&(e.removeChild(r),a-=1),e.appendChild(y(t)),n.setStart(e,a),n.collapse(!0),A(e,n),J&&(r=e.lastChild)&&"BR"===r.nodeName&&e.removeChild(r)}}function O(e,t){var n,o,i=e.previousSibling,r=e.firstChild,a=e.ownerDocument,s="LI"===e.nodeName;if((!s||r&&/^[OU]L$/.test(r.nodeName))&&!L(e))if(i&&f(i,e)&&i.isContentEditable&&e.isContentEditable){if(!d(i)){if(!s)return;o=T(a,"DIV"),o.appendChild(y(i)),i.appendChild(o)}_(e),n=!d(e),i.appendChild(y(e)),n&&b(i,t),r&&O(r,t)}else s&&(i=T(a,"DIV"),e.insertBefore(i,r),E(i,t))}function R(e){this.isShiftDown=e.shiftKey}function D(e,t,n){var o,i;if(e||(e={}),t)for(o in t)!n&&o in e||(i=t[o],e[o]=i&&i.constructor===Object?D(e[o],i,n):i);return e}function P(e,t){e.nodeType===W&&(e=e.body);var n,o=e.ownerDocument,i=o.defaultView;this._win=i,this._doc=o,this._root=e,this._events={},this._isFocused=!1,this._lastSelection=null,ae&&this.addEventListener("beforedeactivate",this.getSelection),this._hasZWS=!1,this._lastAnchorNode=null,this._lastFocusNode=null,this._path="",this._willUpdatePath=!1,"onselectionchange"in o?this.addEventListener("selectionchange",this._updatePathOnEvent):(this.addEventListener("keyup",this._updatePathOnEvent),this.addEventListener("mouseup",this._updatePathOnEvent)),this._undoIndex=-1,this._undoStack=[],this._undoStackLength=0,this._isInUndoState=!1,this._ignoreChange=!1,this._ignoreAllChanges=!1,se?(n=new MutationObserver(this._docWasChanged.bind(this)),n.observe(e,{childList:!0,attributes:!0,characterData:!0,subtree:!0}),this._mutation=n):this.addEventListener("keyup",this._keyUpDetectChange),this._restoreSelection=!1,this.addEventListener("blur",U),this.addEventListener("mousedown",I),this.addEventListener("touchstart",I),this.addEventListener("focus",w),this._awaitingPaste=!1,this.addEventListener(X?"beforecut":"cut",nt),this.addEventListener("copy",ot),this.addEventListener("keydown",R),this.addEventListener("keyup",R),this.addEventListener(X?"beforepaste":"paste",it),this.addEventListener("drop",rt),this.addEventListener(J?"keypress":"keydown",Ie),this._keyHandlers=Object.create(He),this.setConfig(t),X&&(i.Text.prototype.splitText=function(e){var t=this.ownerDocument.createTextNode(this.data.slice(e)),n=this.nextSibling,o=this.parentNode,i=this.length-e;return n?o.insertBefore(t,n):o.appendChild(t),i&&this.deleteData(e,i),t}),e.setAttribute("contenteditable","true");try{o.execCommand("enableObjectResizing",!1,"false"),o.execCommand("enableInlineTableEditing",!1,"false")}catch(e){}e.__squire__=this,this.setHTML("")}function U(){this._restoreSelection=!0}function I(){this._restoreSelection=!1}function w(){this._restoreSelection&&this.setSelection(this._lastSelection)}function F(e,t,n){var o,i;for(o=t.firstChild;o;o=i){if(i=o.nextSibling,a(o)){if(o.nodeType===H||"BR"===o.nodeName||"IMG"===o.nodeName){n.appendChild(o);continue}}else if(s(o)){n.appendChild(e.createDefaultBlock([F(e,o,e._doc.createDocumentFragment())]));continue}F(e,o,n)}return n}var M=1,H=3,W=9,z=11,q=1,K="​",G=e.defaultView,Z=navigator.userAgent,j=/Android/.test(Z),Q=/iP(?:ad|hone|od)/.test(Z),$=/Mac OS X/.test(Z),V=/Windows NT/.test(Z),Y=/Gecko\//.test(Z),X=/Trident\/[456]\./.test(Z),J=!!G.opera,ee=/Edge\//.test(Z),te=!ee&&/WebKit\//.test(Z),ne=/Trident\/[4567]\./.test(Z),oe=$?"meta-":"ctrl-",ie=X||J,re=X||te,ae=X,se="undefined"!=typeof MutationObserver,de="undefined"!=typeof WeakMap,le=/[^ \t\r\n]/,ce=Array.prototype.indexOf;Object.create||(Object.create=function(e){var t=function(){};return t.prototype=e,new t});var he={1:1,2:2,3:4,8:128,9:256,11:1024},ue=function(){return!0};n.prototype.nextNode=function(){for(var e,t=this.currentNode,n=this.root,o=this.nodeType,i=this.filter;;){for(e=t.firstChild;!e&&t&&t!==n;)(e=t.nextSibling)||(t=t.parentNode);if(!e)return null;if(he[e.nodeType]&o&&i(e))return this.currentNode=e,e;t=e}},n.prototype.previousNode=function(){for(var e,t=this.currentNode,n=this.root,o=this.nodeType,i=this.filter;;){if(t===n)return null;if(e=t.previousSibling)for(;t=e.lastChild;)e=t;else e=t.parentNode;if(!e)return null;if(he[e.nodeType]&o&&i(e))return this.currentNode=e,e;t=e}},n.prototype.previousPONode=function(){for(var e,t=this.currentNode,n=this.root,o=this.nodeType,i=this.filter;;){for(e=t.lastChild;!e&&t&&t!==n;)(e=t.previousSibling)||(t=t.parentNode);if(!e)return null;if(he[e.nodeType]&o&&i(e))return this.currentNode=e,e;t=e}};var fe=/^(?:#text|A(?:BBR|CRONYM)?|B(?:R|D[IO])?|C(?:ITE|ODE)|D(?:ATA|EL|FN)|EM|FONT|I(?:FRAME|MG|NPUT|NS)?|KBD|Q|R(?:P|T|UBY)|S(?:AMP|MALL|PAN|TR(?:IKE|ONG)|U[BP])?|TIME|U|VAR|WBR)$/,pe={BR:1,HR:1,IFRAME:1,IMG:1,INPUT:1},ge=0,me=1,ve=2,Ce=3,Ne=de?new WeakMap:null,_e=function(e,t){for(var n=e.childNodes;t&&e.nodeType===M;)e=n[t-1],n=e.childNodes,t=n.length;return e},Se=function(e,t){if(e.nodeType===M){var n=e.childNodes;if(t-1,r=e.compareBoundaryPoints(1,o)<1;return!i&&!r}var a=e.compareBoundaryPoints(0,o)<1,s=e.compareBoundaryPoints(2,o)>-1;return a&&s},xe=function(e){for(var t,n=e.startContainer,o=e.startOffset,r=e.endContainer,a=e.endOffset,s=!0;n.nodeType!==H&&(t=n.childNodes[o])&&!i(t);)n=t,o=0;if(a)for(;r.nodeType!==H;){if(!(t=r.childNodes[a-1])||i(t)){if(s&&t&&"BR"===t.nodeName){a-=1,s=!1;continue}break}r=t,a=N(r)}else for(;r.nodeType!==H&&(t=r.firstChild)&&!i(t);)r=t;e.collapsed?(e.setStart(r,a),e.setEnd(n,o)):(e.setStart(n,o),e.setEnd(r,a))},Ae=function(e,t,n,o){var i,r=e.startContainer,a=e.startOffset,s=e.endContainer,d=e.endOffset,l=!0;for(t||(t=e.commonAncestorContainer),n||(n=t);!a&&r!==t&&r!==o;)i=r.parentNode,a=ce.call(i.childNodes,r),r=i;for(;;){if(l&&s.nodeType!==H&&s.childNodes[d]&&"BR"===s.childNodes[d].nodeName&&(d+=1,l=!1),s===n||s===o||d!==N(s))break;i=s.parentNode,d=ce.call(i.childNodes,s)+1,s=i}e.setStart(r,a),e.setEnd(s,d)},Le=function(e,t){var n,o=e.startContainer;return a(o)?n=c(o,t):o!==t&&s(o)?n=o:(n=_e(o,e.startOffset),n=h(n,t)),n&&ke(e,n,!0)?n:null},Be=function(e,t){var n,o,i=e.endContainer;if(a(i))n=c(i,t);else if(i!==t&&s(i))n=i;else{if(!(n=Se(i,e.endOffset))||!v(t,n))for(n=t;o=n.lastChild;)n=o;n=c(n,t)}return n&&ke(e,n,!0)?n:null},Oe=new n(null,4|q,function(e){return e.nodeType===H?le.test(e.data):"IMG"===e.nodeName}),Re=function(e,t){var n,o=e.startContainer,i=e.startOffset;if(Oe.root=null,o.nodeType===H){if(i)return!1;n=o}else if(n=Se(o,i),n&&!v(t,n)&&(n=null),!n&&(n=_e(o,i),n.nodeType===H&&n.length))return!1;return Oe.currentNode=n,Oe.root=Le(e,t),!Oe.previousNode()},De=function(e,t){var n,o=e.endContainer,i=e.endOffset;if(Oe.root=null,o.nodeType===H){if((n=o.data.length)&&i-1||!Y&&ce.call(i,"text/plain")>-1&&ce.call(i,"text/rtf")<0))return e.preventDefault(),void(!d&&(r=a.getData("text/html"))?this.insertHTML(r,!0):((r=a.getData("text/plain"))||(r=a.getData("text/uri-list")))&&this.insertPlainText(r,!0));this._awaitingPaste=!0;var f=this._doc.body,p=this.getSelection(),g=p.startContainer,m=p.startOffset,v=p.endContainer,C=p.endOffset,N=this.createElement("DIV",{contenteditable:"true",style:"position:fixed; overflow:hidden; top:0; right:100%; width:1px; height:1px;"});f.appendChild(N),p.selectNodeContents(N),this.setSelection(p),setTimeout(function(){try{u._awaitingPaste=!1;for(var e,t,n="",o=N;N=o;)o=N.nextSibling,_(N),e=N.firstChild,e&&e===N.lastChild&&"DIV"===e.nodeName&&(N=e),n+=N.innerHTML;t=u.createRange(g,m,v,C),u.setSelection(t),n&&u.insertHTML(n,!0)}catch(e){u.didError(e)}},0)},rt=function(e){for(var t=e.dataTransfer.types,n=t.length,o=!1,i=!1;n--;)switch(t[n]){case"text/plain":o=!0;break;case"text/html":i=!0;break;default:return}(i||o)&&this.saveUndoState()},at=P.prototype,st=function(e,t,n){var o=n._doc,i=e?DOMPurify.sanitize(e,{ALLOW_UNKNOWN_PROTOCOLS:!0,WHOLE_DOCUMENT:!1,RETURN_DOM:!0,RETURN_DOM_FRAGMENT:!0}):null;return i?o.importNode(i,!0):o.createDocumentFragment()};at.setConfig=function(e){return e=D({blockTag:"DIV",blockAttributes:null,tagAttributes:{blockquote:null,ul:null,ol:null,li:null,a:null},classNames:{colour:"colour",fontFamily:"font",fontSize:"size",highlight:"highlight"},leafNodeNames:pe,undo:{documentSizeThreshold:-1,undoLimit:-1},isInsertedHTMLSanitized:!0,isSetHTMLSanitized:!0,sanitizeToDOMFragment:"undefined"!=typeof DOMPurify&&DOMPurify.isSupported?st:null,willCutCopy:null,allowedBlocks:[]},e,!0),e.blockTag=e.blockTag.toUpperCase(),this._config=e,this},at.createElement=function(e,t,n){return T(this._doc,e,t,n)},at.createDefaultBlock=function(e){var t=this._config;return E(this.createElement(t.blockTag,t.blockAttributes,e),this._root)},at.didError=function(e){console.log(e)},at.getDocument=function(){return this._doc},at.getRoot=function(){return this._root},at.modifyDocument=function(e){var t=this._mutation;t&&(t.takeRecords().length&&this._docWasChanged(),t.disconnect()),this._ignoreAllChanges=!0,e(),this._ignoreAllChanges=!1,t&&(t.observe(this._root,{childList:!0,attributes:!0,characterData:!0,subtree:!0}),this._ignoreChange=!1)};var dt={pathChange:1,select:1,input:1,undoStateChange:1};at.fireEvent=function(e,t){var n,o,i,r=this._events[e];if(/^(?:focus|blur)/.test(e))if(n=this._root===this._doc.activeElement,"focus"===e){if(!n||this._isFocused)return this;this._isFocused=!0}else{if(n||!this._isFocused)return this;this._isFocused=!1}if(r)for(t||(t={}),t.type!==e&&(t.type=e),r=r.slice(),o=r.length;o--;){i=r[o];try{i.handleEvent?i.handleEvent(t):i.call(this,t)}catch(t){t.details="Squire: fireEvent error. Event type: "+e,this.didError(t)}}return this},at.destroy=function(){var e,t=this._events;for(e in t)this.removeEventListener(e);this._mutation&&this._mutation.disconnect(),delete this._root.__squire__,this._undoIndex=-1,this._undoStack=[],this._undoStackLength=0},at.handleEvent=function(e){this.fireEvent(e.type,e)},at.addEventListener=function(e,t){var n=this._events[e],o=this._root;return t?(n||(n=this._events[e]=[],dt[e]||("selectionchange"===e&&(o=this._doc),o.addEventListener(e,this,!0))),n.push(t),this):(this.didError({name:"Squire: addEventListener with null or undefined fn",message:"Event type: "+e}),this)},at.removeEventListener=function(e,t){var n,o=this._events[e],i=this._root;if(o){if(t)for(n=o.length;n--;)o[n]===t&&o.splice(n,1);else o.length=0;o.length||(delete this._events[e],dt[e]||("selectionchange"===e&&(i=this._doc),i.removeEventListener(e,this,!0)))}return this},at.createRange=function(e,t,n,o){if(e instanceof this._win.Range)return e.cloneRange();var i=this._doc.createRange();return i.setStart(e,t),n?i.setEnd(n,o):i.setEnd(e,t),i},at.getCursorPosition=function(e){if(!e&&!(e=this.getSelection())||!e.getBoundingClientRect)return null;var t,n,o=e.getBoundingClientRect();return o&&!o.top&&(this._ignoreChange=!0,t=this._doc.createElement("SPAN"),t.textContent=K,ye(e,t),o=t.getBoundingClientRect(),n=t.parentNode,n.removeChild(t),A(n,e),this._ignoreChange=!1),o},at._moveCursorTo=function(e){var t=this._root,n=this.createRange(t,e?0:t.childNodes.length);return xe(n),this.setSelection(n),this},at.moveCursorToStart=function(){return this._moveCursorTo(!0)},at.moveCursorToEnd=function(){return this._moveCursorTo(!1)};var lt=function(e){return e._win.getSelection()||null};at.setSelection=function(e){if(e)if(this._lastSelection=e,this._isFocused)if(j&&!this._restoreSelection)U.call(this),this.blur(),this.focus();else{Q&&this._win.focus();var t=lt(this);t&&(t.removeAllRanges(),t.addRange(e))}else U.call(this);return this},at.getSelection=function(){var e,t,n,o,r=lt(this),a=this._root;return this._isFocused&&r&&r.rangeCount&&(e=r.getRangeAt(0).cloneRange(),t=e.startContainer,n=e.endContainer,t&&i(t)&&e.setStartBefore(t),n&&i(n)&&e.setEndBefore(n)),e&&v(a,e.commonAncestorContainer)?this._lastSelection=e:(e=this._lastSelection,o=e.commonAncestorContainer,v(o.ownerDocument,o)||(e=null)),e||(e=this.createRange(a.firstChild,0)),e},at.getSelectedText=function(){var e=this.getSelection();if(!e||e.collapsed)return"";var t,o=new n(e.commonAncestorContainer,4|q,function(t){return ke(e,t,!0)}),i=e.startContainer,r=e.endContainer,s=o.currentNode=i,d="",l=!1;for(o.filter(s)||(s=o.nextNode());s;)s.nodeType===H?(t=s.data)&&/\S/.test(t)&&(s===r&&(t=t.slice(0,e.endOffset)),s===i&&(t=t.slice(e.startOffset)),d+=t,l=!0):("BR"===s.nodeName||l&&!a(s))&&(d+="\n",l=!1),s=o.nextNode();return d},at.getPath=function(){return this._path};var ct=function(e,t){for(var o,i,r,s=new n(e,4);i=s.nextNode();)for(;(r=i.data.indexOf(K))>-1&&(!t||i.parentNode!==t);){if(1===i.length){do{o=i.parentNode,o.removeChild(i),i=o,s.currentNode=o}while(a(i)&&!N(i));break}i.deleteData(r,1)}};at._didAddZWS=function(){this._hasZWS=!0},at._removeZWS=function(){this._hasZWS&&(ct(this._root),this._hasZWS=!1)},at._updatePath=function(e,t){if(e){var n,o=e.startContainer,i=e.endContainer;(t||o!==this._lastAnchorNode||i!==this._lastFocusNode)&&(this._lastAnchorNode=o,this._lastFocusNode=i, +n=o&&i?o===i?C(i,this._root,this._config):"(selection)":"",this._path!==n&&(this._path=n,this.fireEvent("pathChange",{path:n}))),this.fireEvent(e.collapsed?"cursor":"select",{range:e})}},at._updatePathOnEvent=function(e){var t=this;t._isFocused&&!t._willUpdatePath&&(t._willUpdatePath=!0,setTimeout(function(){t._willUpdatePath=!1,t._updatePath(t.getSelection())},0))},at.focus=function(){if(ne){try{this._root.setActive()}catch(e){}this.fireEvent("focus")}else this._root.focus();return this},at.blur=function(){return this._root.blur(),ne&&this.fireEvent("blur"),this};var ht="squire-selection-end";at._saveRangeToBookmark=function(e){var t,n=this.createElement("INPUT",{id:"squire-selection-start",type:"hidden"}),o=this.createElement("INPUT",{id:ht,type:"hidden"});ye(e,n),e.collapse(!1),ye(e,o),2&n.compareDocumentPosition(o)&&(n.id=ht,o.id="squire-selection-start",t=n,n=o,o=t),e.setStartAfter(n),e.setEndBefore(o)},at._getRangeAndRemoveBookmark=function(e){var t=this._root,n=t.querySelector("#squire-selection-start"),o=t.querySelector("#"+ht);if(n&&o){var i=n.parentNode,r=o.parentNode,a=ce.call(i.childNodes,n),s=ce.call(r.childNodes,o);i===r&&(s-=1),_(n),_(o),e||(e=this._doc.createRange()),e.setStart(i,a),e.setEnd(r,s),A(i,e),i!==r&&A(r,e),e.collapsed&&(i=e.startContainer,i.nodeType===H&&(r=i.childNodes[e.startOffset],r&&r.nodeType===H||(r=i.childNodes[e.startOffset-1]),r&&r.nodeType===H&&(e.setStart(r,0),e.collapse(!0))))}return e||null},at._keyUpDetectChange=function(e){var t=e.keyCode;e.ctrlKey||e.metaKey||e.altKey||!(t<16||t>20)||!(t<33||t>45)||this._docWasChanged()},at._docWasChanged=function(){if(de&&(Ne=new WeakMap),!this._ignoreAllChanges){if(se&&this._ignoreChange)return void(this._ignoreChange=!1);this._isInUndoState&&(this._isInUndoState=!1,this.fireEvent("undoStateChange",{canUndo:!0,canRedo:!1})),this.fireEvent("input")}},at._recordUndoState=function(e,t){if(!this._isInUndoState||t){var n,o=this._undoIndex,i=this._undoStack,r=this._config.undo,a=r.documentSizeThreshold,s=r.undoLimit;t||(o+=1),o-1&&2*n.length>a&&s>-1&&o>s&&(i.splice(0,o-s),o=s,this._undoStackLength=s),i[o]=n,this._undoIndex=o,this._undoStackLength+=1,this._isInUndoState=!0}},at.saveUndoState=function(e){return e===t&&(e=this.getSelection()),this._recordUndoState(e,this._isInUndoState),this._getRangeAndRemoveBookmark(e),this},at.undo=function(){if(0!==this._undoIndex||!this._isInUndoState){this._recordUndoState(this.getSelection(),!1),this._undoIndex-=1,this._setHTML(this._undoStack[this._undoIndex]);var e=this._getRangeAndRemoveBookmark();e&&this.setSelection(e),this._isInUndoState=!0,this.fireEvent("undoStateChange",{canUndo:0!==this._undoIndex,canRedo:!0}),this.fireEvent("input")}return this},at.redo=function(){var e=this._undoIndex,t=this._undoStackLength;if(e+1c&&h.splitText(c),h===s&&l&&(h=h.splitText(l),d===s&&(d=h,c-=l),s=h,l=0),i=this.createElement(e,t),S(h,i),i.appendChild(h))}while(r.nextNode());d.nodeType!==H&&(h.nodeType===H?(d=h,c=h.length):(d=h.parentNode,c=1)),o=this.createRange(s,l,d,c)}return o},at._removeFormat=function(e,t,n,o){this._saveRangeToBookmark(n);var i,r=this._doc;n.collapsed&&(re?(i=r.createTextNode(K),this._didAddZWS()):i=r.createTextNode(""),ye(n,i));for(var s=n.commonAncestorContainer;a(s);)s=s.parentNode;var d=n.startContainer,l=n.startOffset,c=n.endContainer,h=n.endOffset,u=[],f=function(e,t){if(!ke(n,e,!1)){var o,i,r=e.nodeType===H;if(!ke(n,e,!0))return void("INPUT"===e.nodeName||r&&!e.data||u.push([t,e]));if(r)e===c&&h!==e.length&&u.push([t,e.splitText(h)]),e===d&&l&&(e.splitText(l),u.push([t,e]));else for(o=e.firstChild;o;o=i)i=o.nextSibling,f(o,t)}},g=Array.prototype.filter.call(s.getElementsByTagName(e),function(o){return ke(n,o,!0)&&p(o,e,t)});return o||g.forEach(function(e){f(e,e)}),u.forEach(function(e){var t=e[0].cloneNode(!1),n=e[1];S(n,t),t.appendChild(n)}),g.forEach(function(e){S(e,y(e))}),this._getRangeAndRemoveBookmark(n),i&&n.collapse(!1),A(s,n),n},at.changeFormat=function(e,t,n,o){return n||(n=this.getSelection())?(this.saveUndoState(n),t&&(n=this._removeFormat(t.tag.toUpperCase(),t.attributes||{},n,o)),e&&(n=this._addFormat(e.tag.toUpperCase(),e.attributes||{},n)),this.setSelection(n),this._updatePath(n,!0),se||this._docWasChanged(),this):this};var ut={DT:"DD",DD:"DT",LI:"LI",PRE:"PRE"},ft=function(e,t,n,o){var i=ut[t.nodeName],r=null,a=k(n,o,t.parentNode,e._root),s=e._config;return i||(i=s.blockTag,r=s.blockAttributes),p(a,i,r)||(t=T(a.ownerDocument,i,r),a.dir&&(t.dir=a.dir),S(a,t),t.appendChild(y(a)),a=t),a};at.forEachBlock=function(e,t,n){if(!n&&!(n=this.getSelection()))return this;t&&this.saveUndoState(n);var o=this._root,i=Le(n,o),r=Be(n,o);if(i&&r)do{if(e(i)||i===r)break}while(i=h(i,o));return t&&(this.setSelection(n),this._updatePath(n,!0),se||this._docWasChanged()),this},at.modifyBlocks=function(e,t){if(!t&&!(t=this.getSelection()))return this;this._recordUndoState(t,this._isInUndoState);var n,o=this._root;return Pe(t,o),Ae(t,o,o,o),n=Te(t,o,o),ye(t,e.call(this,n)),t.endOffset]+|\([^\s()<>]+\))+(?:\((?:[^\s()<>]+|(?:\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))|([\w\-.%+]+@(?:[\w\-]+\.)+[A-Z]{2,}\b)(?:\?[^&?\s]+=[^&?\s]+(?:&[^&?\s]+=[^&?\s]+)*)?/i;var yt=function(e,t,o){var i,r,a,s,d,l,c,h=e.ownerDocument,u=new n(e,4,function(e){return!g(e,t,"A")}),f=o.linkRegExp,p=o._config.tagAttributes.a;if(f)for(;i=u.nextNode();)for(r=i.data,a=i.parentNode;s=f.exec(r);)d=s.index,l=d+s[0].length,d&&(c=h.createTextNode(r.slice(0,d)),a.insertBefore(c,i)),c=o.createElement("A",D({href:s[1]?/^(?:ht|f)tps?:/i.test(s[1])?s[1]:"http://"+s[1]:"mailto:"+s[0]},p,!1)),c.textContent=r.slice(d,l),a.insertBefore(c,i),i.data=r=r.slice(l)};at.insertHTML=function(e,t){var n,o,i,r,a,s,d,l=this._config,c=l.isInsertedHTMLSanitized?l.sanitizeToDOMFragment:null,u=this.getSelection(),f=this._doc;"function"==typeof c?r=c(e,t,this):(t&&(n=e.indexOf("\x3c!--StartFragment--\x3e"),o=e.lastIndexOf("\x3c!--EndFragment--\x3e"),n>-1&&o>-1&&(e=e.slice(n+20,o))),/<\/td>((?!<\/tr>)[\s\S])*$/i.test(e)&&(e="
"+e+""),/<\/tr>((?!<\/table>)[\s\S])*$/i.test(e)&&(e="
"+e+"
"),i=this.createElement("DIV"),i.innerHTML=e,r=f.createDocumentFragment(),r.appendChild(y(i))),this.saveUndoState(u);try{for(a=this._root,s=r,d={fragment:r,preventDefault:function(){this.defaultPrevented=!0},defaultPrevented:!1},yt(r,r,this),Ve(r,l),et(r,a,!1),Ye(r),r.normalize();s=h(s,r);)E(s,a);t&&this.fireEvent("willPaste",d),d.defaultPrevented||(be(u,d.fragment,a),se||this._docWasChanged(),u.collapse(!1),this._ensureBottomLine()),this.setSelection(u),this._updatePath(u,!0),t&&this.focus()}catch(e){this.didError(e)}return this};var Tt=function(e){return e.split("&").join("&").split("<").join("<").split(">").join(">").split('"').join(""")};at.insertPlainText=function(e,t){var n=this.getSelection();if(n.collapsed&&g(n.startContainer,this._root,"PRE")){var o,i,r=n.startContainer,a=n.startOffset;return r&&r.nodeType===H||(o=this._doc.createTextNode(""),r.insertBefore(o,r.childNodes[a]),r=o,a=0),i={text:e,preventDefault:function(){this.defaultPrevented=!0},defaultPrevented:!1},t&&this.fireEvent("willPaste",i),i.defaultPrevented||(e=i.text,r.insertData(a,e),n.setStart(r,a+e.length),n.collapse(!0)),this.setSelection(n),this}var s,d,l,c,h=e.split("\n"),u=this._config,f=u.blockTag,p=u.blockAttributes,m="",v="<"+f;for(s in p)v+=" "+s+'="'+Tt(p[s])+'"';for(v+=">",d=0,l=h.length;d")+m;return this.insertHTML(h.join(""),t)};var Et=function(e,t,n){return function(){return this[e](t,n),this.focus()}};at.addStyles=function(e){if(e){var t=this._doc.documentElement.firstChild,n=this.createElement("STYLE",{type:"text/css"});n.appendChild(this._doc.createTextNode(e)),t.appendChild(n)}return this},at.bold=Et("changeFormat",{tag:"B"}),at.italic=Et("changeFormat",{tag:"I"}),at.underline=Et("changeFormat",{tag:"U"}),at.strikethrough=Et("changeFormat",{tag:"S"}),at.subscript=Et("changeFormat",{tag:"SUB"},{tag:"SUP"}),at.superscript=Et("changeFormat",{tag:"SUP"},{tag:"SUB"}),at.removeBold=Et("changeFormat",null,{tag:"B"}),at.removeItalic=Et("changeFormat",null,{tag:"I"}),at.removeUnderline=Et("changeFormat",null,{tag:"U"}),at.removeStrikethrough=Et("changeFormat",null,{tag:"S"}),at.removeSubscript=Et("changeFormat",null,{tag:"SUB"}),at.removeSuperscript=Et("changeFormat",null,{tag:"SUP"}),at.makeLink=function(e,t){var n=this.getSelection();if(n.collapsed){var o=e.indexOf(":")+1;if(o)for(;"/"===e[o];)o+=1;ye(n,this._doc.createTextNode(e.slice(o)))}return t=D(D({href:e},t,!0),this._config.tagAttributes.a,!1),this.changeFormat({tag:"A",attributes:t},{tag:"A"},n),this.focus()},at.removeLink=function(){return this.changeFormat(null,{tag:"A"},this.getSelection(),!0),this.focus()},at.setFontFace=function(e){var t=this._config.classNames.fontFamily;return this.changeFormat(e?{tag:"SPAN",attributes:{class:t,style:"font-family: "+e+", sans-serif;"}}:null,{tag:"SPAN",attributes:{class:t}}),this.focus()},at.setFontSize=function(e){var t=this._config.classNames.fontSize;return this.changeFormat(e?{tag:"SPAN",attributes:{class:t,style:"font-size: "+("number"==typeof e?e+"px":e)}}:null,{tag:"SPAN",attributes:{class:t}}),this.focus()},at.setTextColour=function(e){var t=this._config.classNames.colour;return this.changeFormat(e?{tag:"SPAN",attributes:{class:t,style:"color:"+e}}:null,{tag:"SPAN",attributes:{class:t}}),this.focus()},at.setHighlightColour=function(e){var t=this._config.classNames.highlight;return this.changeFormat(e?{tag:"SPAN",attributes:{class:t,style:"background-color:"+e}}:e,{tag:"SPAN",attributes:{class:t}}),this.focus()},at.setTextAlignment=function(e){return this.forEachBlock(function(t){var n=t.className.split(/\s+/).filter(function(e){return!!e&&!/^align/.test(e)}).join(" ");e?(t.className=n+" align-"+e,t.style.textAlign=e):(t.className=n,t.style.textAlign="")},!0),this.focus()},at.setTextDirection=function(e){return this.forEachBlock(function(t){e?t.dir=e:t.removeAttribute("dir")},!0),this.focus()};var bt=function(e){for(var t,o=this._root,i=this._doc,r=i.createDocumentFragment(),a=l(e,o);t=a.nextNode();){var s,d,c=t.querySelectorAll("BR"),h=[],u=c.length;for(s=0;s-1;)a.appendChild(d.createTextNode(r.slice(0,s))),a.appendChild(d.createElement("BR")),r=r.slice(s+1);i.parentNode.insertBefore(a,i),i.data=r}b(t,l),S(t,y(t))}return e};at.code=function(){var e=this.getSelection();return e.collapsed||d(e.commonAncestorContainer)?this.modifyBlocks(bt,e):this.changeFormat({tag:"CODE",attributes:this._config.tagAttributes.code},null,e),this.focus()},at.removeCode=function(){var e=this.getSelection();return g(e.commonAncestorContainer,this._root,"PRE")?this.modifyBlocks(kt,e):this.changeFormat(null,{tag:"CODE"},e),this.focus()},at.toggleCode=function(){return this.hasFormat("PRE")||this.hasFormat("CODE")?this.removeCode():this.code(),this},at.removeAllFormatting=function(e){if(!e&&!(e=this.getSelection())||e.collapsed)return this;for(var t=this._root,n=e.commonAncestorContainer;n&&!s(n);)n=n.parentNode;if(n||(Pe(e,t),n=t),n.nodeType===H)return this;this.saveUndoState(e),Ae(e,n,n,t);for(var o,i,r=n.ownerDocument,a=e.startContainer,d=e.startOffset,l=e.endContainer,c=e.endOffset,h=r.createDocumentFragment(),u=r.createDocumentFragment(),f=k(l,c,n,t),p=k(a,d,n,t);p!==f;)o=p.nextSibling,h.appendChild(p),p=o;return F(this,h,u),u.normalize(),p=u.firstChild,o=u.lastChild,i=n.childNodes,p?(n.insertBefore(u,f),d=ce.call(i,p),c=ce.call(i,o)+1):(d=ce.call(i,f),c=d),e.setStart(n,d),e.setEnd(n,c),A(n,e),xe(e),this.setSelection(e),this._updatePath(e,!0),this.focus()},at.increaseQuoteLevel=Et("modifyBlocks",pt),at.decreaseQuoteLevel=Et("modifyBlocks",gt),at.makeUnorderedList=Et("modifyBlocks",Ct),at.makeOrderedList=Et("modifyBlocks",Nt),at.removeList=Et("modifyBlocks",_t),P.isInline=a,P.isBlock=s,P.isContainer=d,P.getBlockWalker=l,P.getPreviousBlock=c,P.getNextBlock=h,P.areAlike=f,P.hasTagAttributes=p,P.getNearest=g,P.isOrContains=v,P.detach=_,P.replaceWith=S,P.empty=y,P.getNodeBefore=_e,P.getNodeAfter=Se,P.insertNodeInRange=ye,P.extractContentsOfRange=Te,P.deleteContentsOfRange=Ee,P.insertTreeFragmentIntoRange=be,P.isNodeContainedInRange=ke,P.moveRangeBoundariesDownTree=xe,P.moveRangeBoundariesUpTree=Ae,P.getStartBlockOfRange=Le,P.getEndBlockOfRange=Be,P.contentWalker=Oe,P.rangeDoesStartAtBlockBoundary=Re,P.rangeDoesEndAtBlockBoundary=De,P.expandRangeToBlockBoundaries=Pe,P.onPaste=it,P.addLinks=yt,P.splitBlock=ft,P.startSelectionId="squire-selection-start",P.endSelectionId=ht, true?module.exports=P:undefined}(document); + +/***/ }), +/* 56 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview Check whether the given variable is a string or not. + * @author NHN FE Development Lab + */ + + + +/** + * Check whether the given variable is a boolean or not. + * If the given variable is a boolean, return true. + * @param {*} obj - Target for checking + * @returns {boolean} Is boolean? + * @memberof module:type + */ +function isBoolean(obj) { + return typeof obj === 'boolean' || obj instanceof Boolean; +} + +module.exports = isBoolean; + + +/***/ }), +/* 57 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/** + * A collection of shims that provide minimal functionality of the ES6 collections. + * + * These implementations are not meant to be used outside of the ResizeObserver + * modules as they cover only a limited range of use cases. + */ +/* eslint-disable require-jsdoc, valid-jsdoc */ +var MapShim = (function () { + if (typeof Map !== 'undefined') { + return Map; + } + /** + * Returns index in provided array that matches the specified key. + * + * @param {Array} arr + * @param {*} key + * @returns {number} + */ + function getIndex(arr, key) { + var result = -1; + arr.some(function (entry, index) { + if (entry[0] === key) { + result = index; + return true; + } + return false; + }); + return result; + } + return /** @class */ (function () { + function class_1() { + this.__entries__ = []; + } + Object.defineProperty(class_1.prototype, "size", { + /** + * @returns {boolean} + */ + get: function () { + return this.__entries__.length; + }, + enumerable: true, + configurable: true + }); + /** + * @param {*} key + * @returns {*} + */ + class_1.prototype.get = function (key) { + var index = getIndex(this.__entries__, key); + var entry = this.__entries__[index]; + return entry && entry[1]; + }; + /** + * @param {*} key + * @param {*} value + * @returns {void} + */ + class_1.prototype.set = function (key, value) { + var index = getIndex(this.__entries__, key); + if (~index) { + this.__entries__[index][1] = value; + } + else { + this.__entries__.push([key, value]); + } + }; + /** + * @param {*} key + * @returns {void} + */ + class_1.prototype.delete = function (key) { + var entries = this.__entries__; + var index = getIndex(entries, key); + if (~index) { + entries.splice(index, 1); + } + }; + /** + * @param {*} key + * @returns {void} + */ + class_1.prototype.has = function (key) { + return !!~getIndex(this.__entries__, key); + }; + /** + * @returns {void} + */ + class_1.prototype.clear = function () { + this.__entries__.splice(0); + }; + /** + * @param {Function} callback + * @param {*} [ctx=null] + * @returns {void} + */ + class_1.prototype.forEach = function (callback, ctx) { + if (ctx === void 0) { ctx = null; } + for (var _i = 0, _a = this.__entries__; _i < _a.length; _i++) { + var entry = _a[_i]; + callback.call(ctx, entry[1], entry[0]); + } + }; + return class_1; + }()); +})(); + +/** + * Detects whether window and document objects are available in current environment. + */ +var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && window.document === document; + +// Returns global object of a current environment. +var global$1 = (function () { + if (typeof global !== 'undefined' && global.Math === Math) { + return global; + } + if (typeof self !== 'undefined' && self.Math === Math) { + return self; + } + if (typeof window !== 'undefined' && window.Math === Math) { + return window; + } + // eslint-disable-next-line no-new-func + return Function('return this')(); +})(); + +/** + * A shim for the requestAnimationFrame which falls back to the setTimeout if + * first one is not supported. + * + * @returns {number} Requests' identifier. + */ +var requestAnimationFrame$1 = (function () { + if (typeof requestAnimationFrame === 'function') { + // It's required to use a bounded function because IE sometimes throws + // an "Invalid calling object" error if rAF is invoked without the global + // object on the left hand side. + return requestAnimationFrame.bind(global$1); + } + return function (callback) { return setTimeout(function () { return callback(Date.now()); }, 1000 / 60); }; +})(); + +// Defines minimum timeout before adding a trailing call. +var trailingTimeout = 2; +/** + * Creates a wrapper function which ensures that provided callback will be + * invoked only once during the specified delay period. + * + * @param {Function} callback - Function to be invoked after the delay period. + * @param {number} delay - Delay after which to invoke callback. + * @returns {Function} + */ +function throttle (callback, delay) { + var leadingCall = false, trailingCall = false, lastCallTime = 0; + /** + * Invokes the original callback function and schedules new invocation if + * the "proxy" was called during current request. + * + * @returns {void} + */ + function resolvePending() { + if (leadingCall) { + leadingCall = false; + callback(); + } + if (trailingCall) { + proxy(); + } + } + /** + * Callback invoked after the specified delay. It will further postpone + * invocation of the original function delegating it to the + * requestAnimationFrame. + * + * @returns {void} + */ + function timeoutCallback() { + requestAnimationFrame$1(resolvePending); + } + /** + * Schedules invocation of the original function. + * + * @returns {void} + */ + function proxy() { + var timeStamp = Date.now(); + if (leadingCall) { + // Reject immediately following calls. + if (timeStamp - lastCallTime < trailingTimeout) { + return; + } + // Schedule new call to be in invoked when the pending one is resolved. + // This is important for "transitions" which never actually start + // immediately so there is a chance that we might miss one if change + // happens amids the pending invocation. + trailingCall = true; + } + else { + leadingCall = true; + trailingCall = false; + setTimeout(timeoutCallback, delay); + } + lastCallTime = timeStamp; + } + return proxy; +} + +// Minimum delay before invoking the update of observers. +var REFRESH_DELAY = 20; +// A list of substrings of CSS properties used to find transition events that +// might affect dimensions of observed elements. +var transitionKeys = ['top', 'right', 'bottom', 'left', 'width', 'height', 'size', 'weight']; +// Check if MutationObserver is available. +var mutationObserverSupported = typeof MutationObserver !== 'undefined'; +/** + * Singleton controller class which handles updates of ResizeObserver instances. + */ +var ResizeObserverController = /** @class */ (function () { + /** + * Creates a new instance of ResizeObserverController. + * + * @private + */ + function ResizeObserverController() { + /** + * Indicates whether DOM listeners have been added. + * + * @private {boolean} + */ + this.connected_ = false; + /** + * Tells that controller has subscribed for Mutation Events. + * + * @private {boolean} + */ + this.mutationEventsAdded_ = false; + /** + * Keeps reference to the instance of MutationObserver. + * + * @private {MutationObserver} + */ + this.mutationsObserver_ = null; + /** + * A list of connected observers. + * + * @private {Array} + */ + this.observers_ = []; + this.onTransitionEnd_ = this.onTransitionEnd_.bind(this); + this.refresh = throttle(this.refresh.bind(this), REFRESH_DELAY); + } + /** + * Adds observer to observers list. + * + * @param {ResizeObserverSPI} observer - Observer to be added. + * @returns {void} + */ + ResizeObserverController.prototype.addObserver = function (observer) { + if (!~this.observers_.indexOf(observer)) { + this.observers_.push(observer); + } + // Add listeners if they haven't been added yet. + if (!this.connected_) { + this.connect_(); + } + }; + /** + * Removes observer from observers list. + * + * @param {ResizeObserverSPI} observer - Observer to be removed. + * @returns {void} + */ + ResizeObserverController.prototype.removeObserver = function (observer) { + var observers = this.observers_; + var index = observers.indexOf(observer); + // Remove observer if it's present in registry. + if (~index) { + observers.splice(index, 1); + } + // Remove listeners if controller has no connected observers. + if (!observers.length && this.connected_) { + this.disconnect_(); + } + }; + /** + * Invokes the update of observers. It will continue running updates insofar + * it detects changes. + * + * @returns {void} + */ + ResizeObserverController.prototype.refresh = function () { + var changesDetected = this.updateObservers_(); + // Continue running updates if changes have been detected as there might + // be future ones caused by CSS transitions. + if (changesDetected) { + this.refresh(); + } + }; + /** + * Updates every observer from observers list and notifies them of queued + * entries. + * + * @private + * @returns {boolean} Returns "true" if any observer has detected changes in + * dimensions of it's elements. + */ + ResizeObserverController.prototype.updateObservers_ = function () { + // Collect observers that have active observations. + var activeObservers = this.observers_.filter(function (observer) { + return observer.gatherActive(), observer.hasActive(); + }); + // Deliver notifications in a separate cycle in order to avoid any + // collisions between observers, e.g. when multiple instances of + // ResizeObserver are tracking the same element and the callback of one + // of them changes content dimensions of the observed target. Sometimes + // this may result in notifications being blocked for the rest of observers. + activeObservers.forEach(function (observer) { return observer.broadcastActive(); }); + return activeObservers.length > 0; + }; + /** + * Initializes DOM listeners. + * + * @private + * @returns {void} + */ + ResizeObserverController.prototype.connect_ = function () { + // Do nothing if running in a non-browser environment or if listeners + // have been already added. + if (!isBrowser || this.connected_) { + return; + } + // Subscription to the "Transitionend" event is used as a workaround for + // delayed transitions. This way it's possible to capture at least the + // final state of an element. + document.addEventListener('transitionend', this.onTransitionEnd_); + window.addEventListener('resize', this.refresh); + if (mutationObserverSupported) { + this.mutationsObserver_ = new MutationObserver(this.refresh); + this.mutationsObserver_.observe(document, { + attributes: true, + childList: true, + characterData: true, + subtree: true + }); + } + else { + document.addEventListener('DOMSubtreeModified', this.refresh); + this.mutationEventsAdded_ = true; + } + this.connected_ = true; + }; + /** + * Removes DOM listeners. + * + * @private + * @returns {void} + */ + ResizeObserverController.prototype.disconnect_ = function () { + // Do nothing if running in a non-browser environment or if listeners + // have been already removed. + if (!isBrowser || !this.connected_) { + return; + } + document.removeEventListener('transitionend', this.onTransitionEnd_); + window.removeEventListener('resize', this.refresh); + if (this.mutationsObserver_) { + this.mutationsObserver_.disconnect(); + } + if (this.mutationEventsAdded_) { + document.removeEventListener('DOMSubtreeModified', this.refresh); + } + this.mutationsObserver_ = null; + this.mutationEventsAdded_ = false; + this.connected_ = false; + }; + /** + * "Transitionend" event handler. + * + * @private + * @param {TransitionEvent} event + * @returns {void} + */ + ResizeObserverController.prototype.onTransitionEnd_ = function (_a) { + var _b = _a.propertyName, propertyName = _b === void 0 ? '' : _b; + // Detect whether transition may affect dimensions of an element. + var isReflowProperty = transitionKeys.some(function (key) { + return !!~propertyName.indexOf(key); + }); + if (isReflowProperty) { + this.refresh(); + } + }; + /** + * Returns instance of the ResizeObserverController. + * + * @returns {ResizeObserverController} + */ + ResizeObserverController.getInstance = function () { + if (!this.instance_) { + this.instance_ = new ResizeObserverController(); + } + return this.instance_; + }; + /** + * Holds reference to the controller's instance. + * + * @private {ResizeObserverController} + */ + ResizeObserverController.instance_ = null; + return ResizeObserverController; +}()); + +/** + * Defines non-writable/enumerable properties of the provided target object. + * + * @param {Object} target - Object for which to define properties. + * @param {Object} props - Properties to be defined. + * @returns {Object} Target object. + */ +var defineConfigurable = (function (target, props) { + for (var _i = 0, _a = Object.keys(props); _i < _a.length; _i++) { + var key = _a[_i]; + Object.defineProperty(target, key, { + value: props[key], + enumerable: false, + writable: false, + configurable: true + }); + } + return target; +}); + +/** + * Returns the global object associated with provided element. + * + * @param {Object} target + * @returns {Object} + */ +var getWindowOf = (function (target) { + // Assume that the element is an instance of Node, which means that it + // has the "ownerDocument" property from which we can retrieve a + // corresponding global object. + var ownerGlobal = target && target.ownerDocument && target.ownerDocument.defaultView; + // Return the local global object if it's not possible extract one from + // provided element. + return ownerGlobal || global$1; +}); + +// Placeholder of an empty content rectangle. +var emptyRect = createRectInit(0, 0, 0, 0); +/** + * Converts provided string to a number. + * + * @param {number|string} value + * @returns {number} + */ +function toFloat(value) { + return parseFloat(value) || 0; +} +/** + * Extracts borders size from provided styles. + * + * @param {CSSStyleDeclaration} styles + * @param {...string} positions - Borders positions (top, right, ...) + * @returns {number} + */ +function getBordersSize(styles) { + var positions = []; + for (var _i = 1; _i < arguments.length; _i++) { + positions[_i - 1] = arguments[_i]; + } + return positions.reduce(function (size, position) { + var value = styles['border-' + position + '-width']; + return size + toFloat(value); + }, 0); +} +/** + * Extracts paddings sizes from provided styles. + * + * @param {CSSStyleDeclaration} styles + * @returns {Object} Paddings box. + */ +function getPaddings(styles) { + var positions = ['top', 'right', 'bottom', 'left']; + var paddings = {}; + for (var _i = 0, positions_1 = positions; _i < positions_1.length; _i++) { + var position = positions_1[_i]; + var value = styles['padding-' + position]; + paddings[position] = toFloat(value); + } + return paddings; +} +/** + * Calculates content rectangle of provided SVG element. + * + * @param {SVGGraphicsElement} target - Element content rectangle of which needs + * to be calculated. + * @returns {DOMRectInit} + */ +function getSVGContentRect(target) { + var bbox = target.getBBox(); + return createRectInit(0, 0, bbox.width, bbox.height); +} +/** + * Calculates content rectangle of provided HTMLElement. + * + * @param {HTMLElement} target - Element for which to calculate the content rectangle. + * @returns {DOMRectInit} + */ +function getHTMLElementContentRect(target) { + // Client width & height properties can't be + // used exclusively as they provide rounded values. + var clientWidth = target.clientWidth, clientHeight = target.clientHeight; + // By this condition we can catch all non-replaced inline, hidden and + // detached elements. Though elements with width & height properties less + // than 0.5 will be discarded as well. + // + // Without it we would need to implement separate methods for each of + // those cases and it's not possible to perform a precise and performance + // effective test for hidden elements. E.g. even jQuery's ':visible' filter + // gives wrong results for elements with width & height less than 0.5. + if (!clientWidth && !clientHeight) { + return emptyRect; + } + var styles = getWindowOf(target).getComputedStyle(target); + var paddings = getPaddings(styles); + var horizPad = paddings.left + paddings.right; + var vertPad = paddings.top + paddings.bottom; + // Computed styles of width & height are being used because they are the + // only dimensions available to JS that contain non-rounded values. It could + // be possible to utilize the getBoundingClientRect if only it's data wasn't + // affected by CSS transformations let alone paddings, borders and scroll bars. + var width = toFloat(styles.width), height = toFloat(styles.height); + // Width & height include paddings and borders when the 'border-box' box + // model is applied (except for IE). + if (styles.boxSizing === 'border-box') { + // Following conditions are required to handle Internet Explorer which + // doesn't include paddings and borders to computed CSS dimensions. + // + // We can say that if CSS dimensions + paddings are equal to the "client" + // properties then it's either IE, and thus we don't need to subtract + // anything, or an element merely doesn't have paddings/borders styles. + if (Math.round(width + horizPad) !== clientWidth) { + width -= getBordersSize(styles, 'left', 'right') + horizPad; + } + if (Math.round(height + vertPad) !== clientHeight) { + height -= getBordersSize(styles, 'top', 'bottom') + vertPad; + } + } + // Following steps can't be applied to the document's root element as its + // client[Width/Height] properties represent viewport area of the window. + // Besides, it's as well not necessary as the itself neither has + // rendered scroll bars nor it can be clipped. + if (!isDocumentElement(target)) { + // In some browsers (only in Firefox, actually) CSS width & height + // include scroll bars size which can be removed at this step as scroll + // bars are the only difference between rounded dimensions + paddings + // and "client" properties, though that is not always true in Chrome. + var vertScrollbar = Math.round(width + horizPad) - clientWidth; + var horizScrollbar = Math.round(height + vertPad) - clientHeight; + // Chrome has a rather weird rounding of "client" properties. + // E.g. for an element with content width of 314.2px it sometimes gives + // the client width of 315px and for the width of 314.7px it may give + // 314px. And it doesn't happen all the time. So just ignore this delta + // as a non-relevant. + if (Math.abs(vertScrollbar) !== 1) { + width -= vertScrollbar; + } + if (Math.abs(horizScrollbar) !== 1) { + height -= horizScrollbar; + } + } + return createRectInit(paddings.left, paddings.top, width, height); +} +/** + * Checks whether provided element is an instance of the SVGGraphicsElement. + * + * @param {Element} target - Element to be checked. + * @returns {boolean} + */ +var isSVGGraphicsElement = (function () { + // Some browsers, namely IE and Edge, don't have the SVGGraphicsElement + // interface. + if (typeof SVGGraphicsElement !== 'undefined') { + return function (target) { return target instanceof getWindowOf(target).SVGGraphicsElement; }; + } + // If it's so, then check that element is at least an instance of the + // SVGElement and that it has the "getBBox" method. + // eslint-disable-next-line no-extra-parens + return function (target) { return (target instanceof getWindowOf(target).SVGElement && + typeof target.getBBox === 'function'); }; +})(); +/** + * Checks whether provided element is a document element (). + * + * @param {Element} target - Element to be checked. + * @returns {boolean} + */ +function isDocumentElement(target) { + return target === getWindowOf(target).document.documentElement; +} +/** + * Calculates an appropriate content rectangle for provided html or svg element. + * + * @param {Element} target - Element content rectangle of which needs to be calculated. + * @returns {DOMRectInit} + */ +function getContentRect(target) { + if (!isBrowser) { + return emptyRect; + } + if (isSVGGraphicsElement(target)) { + return getSVGContentRect(target); + } + return getHTMLElementContentRect(target); +} +/** + * Creates rectangle with an interface of the DOMRectReadOnly. + * Spec: https://drafts.fxtf.org/geometry/#domrectreadonly + * + * @param {DOMRectInit} rectInit - Object with rectangle's x/y coordinates and dimensions. + * @returns {DOMRectReadOnly} + */ +function createReadOnlyRect(_a) { + var x = _a.x, y = _a.y, width = _a.width, height = _a.height; + // If DOMRectReadOnly is available use it as a prototype for the rectangle. + var Constr = typeof DOMRectReadOnly !== 'undefined' ? DOMRectReadOnly : Object; + var rect = Object.create(Constr.prototype); + // Rectangle's properties are not writable and non-enumerable. + defineConfigurable(rect, { + x: x, y: y, width: width, height: height, + top: y, + right: x + width, + bottom: height + y, + left: x + }); + return rect; +} +/** + * Creates DOMRectInit object based on the provided dimensions and the x/y coordinates. + * Spec: https://drafts.fxtf.org/geometry/#dictdef-domrectinit + * + * @param {number} x - X coordinate. + * @param {number} y - Y coordinate. + * @param {number} width - Rectangle's width. + * @param {number} height - Rectangle's height. + * @returns {DOMRectInit} + */ +function createRectInit(x, y, width, height) { + return { x: x, y: y, width: width, height: height }; +} + +/** + * Class that is responsible for computations of the content rectangle of + * provided DOM element and for keeping track of it's changes. + */ +var ResizeObservation = /** @class */ (function () { + /** + * Creates an instance of ResizeObservation. + * + * @param {Element} target - Element to be observed. + */ + function ResizeObservation(target) { + /** + * Broadcasted width of content rectangle. + * + * @type {number} + */ + this.broadcastWidth = 0; + /** + * Broadcasted height of content rectangle. + * + * @type {number} + */ + this.broadcastHeight = 0; + /** + * Reference to the last observed content rectangle. + * + * @private {DOMRectInit} + */ + this.contentRect_ = createRectInit(0, 0, 0, 0); + this.target = target; + } + /** + * Updates content rectangle and tells whether it's width or height properties + * have changed since the last broadcast. + * + * @returns {boolean} + */ + ResizeObservation.prototype.isActive = function () { + var rect = getContentRect(this.target); + this.contentRect_ = rect; + return (rect.width !== this.broadcastWidth || + rect.height !== this.broadcastHeight); + }; + /** + * Updates 'broadcastWidth' and 'broadcastHeight' properties with a data + * from the corresponding properties of the last observed content rectangle. + * + * @returns {DOMRectInit} Last observed content rectangle. + */ + ResizeObservation.prototype.broadcastRect = function () { + var rect = this.contentRect_; + this.broadcastWidth = rect.width; + this.broadcastHeight = rect.height; + return rect; + }; + return ResizeObservation; +}()); + +var ResizeObserverEntry = /** @class */ (function () { + /** + * Creates an instance of ResizeObserverEntry. + * + * @param {Element} target - Element that is being observed. + * @param {DOMRectInit} rectInit - Data of the element's content rectangle. + */ + function ResizeObserverEntry(target, rectInit) { + var contentRect = createReadOnlyRect(rectInit); + // According to the specification following properties are not writable + // and are also not enumerable in the native implementation. + // + // Property accessors are not being used as they'd require to define a + // private WeakMap storage which may cause memory leaks in browsers that + // don't support this type of collections. + defineConfigurable(this, { target: target, contentRect: contentRect }); + } + return ResizeObserverEntry; +}()); + +var ResizeObserverSPI = /** @class */ (function () { + /** + * Creates a new instance of ResizeObserver. + * + * @param {ResizeObserverCallback} callback - Callback function that is invoked + * when one of the observed elements changes it's content dimensions. + * @param {ResizeObserverController} controller - Controller instance which + * is responsible for the updates of observer. + * @param {ResizeObserver} callbackCtx - Reference to the public + * ResizeObserver instance which will be passed to callback function. + */ + function ResizeObserverSPI(callback, controller, callbackCtx) { + /** + * Collection of resize observations that have detected changes in dimensions + * of elements. + * + * @private {Array} + */ + this.activeObservations_ = []; + /** + * Registry of the ResizeObservation instances. + * + * @private {Map} + */ + this.observations_ = new MapShim(); + if (typeof callback !== 'function') { + throw new TypeError('The callback provided as parameter 1 is not a function.'); + } + this.callback_ = callback; + this.controller_ = controller; + this.callbackCtx_ = callbackCtx; + } + /** + * Starts observing provided element. + * + * @param {Element} target - Element to be observed. + * @returns {void} + */ + ResizeObserverSPI.prototype.observe = function (target) { + if (!arguments.length) { + throw new TypeError('1 argument required, but only 0 present.'); + } + // Do nothing if current environment doesn't have the Element interface. + if (typeof Element === 'undefined' || !(Element instanceof Object)) { + return; + } + if (!(target instanceof getWindowOf(target).Element)) { + throw new TypeError('parameter 1 is not of type "Element".'); + } + var observations = this.observations_; + // Do nothing if element is already being observed. + if (observations.has(target)) { + return; + } + observations.set(target, new ResizeObservation(target)); + this.controller_.addObserver(this); + // Force the update of observations. + this.controller_.refresh(); + }; + /** + * Stops observing provided element. + * + * @param {Element} target - Element to stop observing. + * @returns {void} + */ + ResizeObserverSPI.prototype.unobserve = function (target) { + if (!arguments.length) { + throw new TypeError('1 argument required, but only 0 present.'); + } + // Do nothing if current environment doesn't have the Element interface. + if (typeof Element === 'undefined' || !(Element instanceof Object)) { + return; + } + if (!(target instanceof getWindowOf(target).Element)) { + throw new TypeError('parameter 1 is not of type "Element".'); + } + var observations = this.observations_; + // Do nothing if element is not being observed. + if (!observations.has(target)) { + return; + } + observations.delete(target); + if (!observations.size) { + this.controller_.removeObserver(this); + } + }; + /** + * Stops observing all elements. + * + * @returns {void} + */ + ResizeObserverSPI.prototype.disconnect = function () { + this.clearActive(); + this.observations_.clear(); + this.controller_.removeObserver(this); + }; + /** + * Collects observation instances the associated element of which has changed + * it's content rectangle. + * + * @returns {void} + */ + ResizeObserverSPI.prototype.gatherActive = function () { + var _this = this; + this.clearActive(); + this.observations_.forEach(function (observation) { + if (observation.isActive()) { + _this.activeObservations_.push(observation); + } + }); + }; + /** + * Invokes initial callback function with a list of ResizeObserverEntry + * instances collected from active resize observations. + * + * @returns {void} + */ + ResizeObserverSPI.prototype.broadcastActive = function () { + // Do nothing if observer doesn't have active observations. + if (!this.hasActive()) { + return; + } + var ctx = this.callbackCtx_; + // Create ResizeObserverEntry instance for every active observation. + var entries = this.activeObservations_.map(function (observation) { + return new ResizeObserverEntry(observation.target, observation.broadcastRect()); + }); + this.callback_.call(ctx, entries, ctx); + this.clearActive(); + }; + /** + * Clears the collection of active observations. + * + * @returns {void} + */ + ResizeObserverSPI.prototype.clearActive = function () { + this.activeObservations_.splice(0); + }; + /** + * Tells whether observer has active observations. + * + * @returns {boolean} + */ + ResizeObserverSPI.prototype.hasActive = function () { + return this.activeObservations_.length > 0; + }; + return ResizeObserverSPI; +}()); + +// Registry of internal observers. If WeakMap is not available use current shim +// for the Map collection as it has all required methods and because WeakMap +// can't be fully polyfilled anyway. +var observers = typeof WeakMap !== 'undefined' ? new WeakMap() : new MapShim(); +/** + * ResizeObserver API. Encapsulates the ResizeObserver SPI implementation + * exposing only those methods and properties that are defined in the spec. + */ +var ResizeObserver = /** @class */ (function () { + /** + * Creates a new instance of ResizeObserver. + * + * @param {ResizeObserverCallback} callback - Callback that is invoked when + * dimensions of the observed elements change. + */ + function ResizeObserver(callback) { + if (!(this instanceof ResizeObserver)) { + throw new TypeError('Cannot call a class as a function.'); + } + if (!arguments.length) { + throw new TypeError('1 argument required, but only 0 present.'); + } + var controller = ResizeObserverController.getInstance(); + var observer = new ResizeObserverSPI(callback, controller, this); + observers.set(this, observer); + } + return ResizeObserver; +}()); +// Expose public methods of ResizeObserver. +[ + 'observe', + 'unobserve', + 'disconnect' +].forEach(function (method) { + ResizeObserver.prototype[method] = function () { + var _a; + return (_a = observers.get(this))[method].apply(_a, arguments); + }; +}); + +var index = (function () { + // Export existing implementation if available. + if (typeof global$1.ResizeObserver !== 'undefined') { + return global$1.ResizeObserver; + } + return ResizeObserver; +})(); + +/* harmony default export */ __webpack_exports__["a"] = (index); + +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(59))) + +/***/ }), +/* 58 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * @fileoverview This module provides some functions for custom events. And it is implemented in the observer design pattern. + * @author NHN FE Development Lab + */ + + + +var extend = __webpack_require__(7); +var isExisty = __webpack_require__(28); +var isString = __webpack_require__(9); +var isObject = __webpack_require__(54); +var isArray = __webpack_require__(17); +var isFunction = __webpack_require__(27); +var forEach = __webpack_require__(26); + +var R_EVENTNAME_SPLIT = /\s+/g; + +/** + * @class + * @example + * // node, commonjs + * var CustomEvents = require('tui-code-snippet/customEvents/customEvents'); + */ +function CustomEvents() { + /** + * @type {HandlerItem[]} + */ + this.events = null; + + /** + * only for checking specific context event was binded + * @type {object[]} + */ + this.contexts = null; +} + +/** + * Mixin custom events feature to specific constructor + * @param {function} func - constructor + * @example + * var CustomEvents = require('tui-code-snippet/customEvents/customEvents'); // node, commonjs + * + * var model; + * function Model() { + * this.name = ''; + * } + * CustomEvents.mixin(Model); + * + * model = new Model(); + * model.on('change', function() { this.name = 'model'; }, this); + * model.fire('change'); + * alert(model.name); // 'model'; + */ +CustomEvents.mixin = function(func) { + extend(func.prototype, CustomEvents.prototype); +}; + +/** + * Get HandlerItem object + * @param {function} handler - handler function + * @param {object} [context] - context for handler + * @returns {HandlerItem} HandlerItem object + * @private + */ +CustomEvents.prototype._getHandlerItem = function(handler, context) { + var item = {handler: handler}; + + if (context) { + item.context = context; + } + + return item; +}; + +/** + * Get event object safely + * @param {string} [eventName] - create sub event map if not exist. + * @returns {(object|array)} event object. if you supplied `eventName` + * parameter then make new array and return it + * @private + */ +CustomEvents.prototype._safeEvent = function(eventName) { + var events = this.events; + var byName; + + if (!events) { + events = this.events = {}; + } + + if (eventName) { + byName = events[eventName]; + + if (!byName) { + byName = []; + events[eventName] = byName; + } + + events = byName; + } + + return events; +}; + +/** + * Get context array safely + * @returns {array} context array + * @private + */ +CustomEvents.prototype._safeContext = function() { + var context = this.contexts; + + if (!context) { + context = this.contexts = []; + } + + return context; +}; + +/** + * Get index of context + * @param {object} ctx - context that used for bind custom event + * @returns {number} index of context + * @private + */ +CustomEvents.prototype._indexOfContext = function(ctx) { + var context = this._safeContext(); + var index = 0; + + while (context[index]) { + if (ctx === context[index][0]) { + return index; + } + + index += 1; + } + + return -1; +}; + +/** + * Memorize supplied context for recognize supplied object is context or + * name: handler pair object when off() + * @param {object} ctx - context object to memorize + * @private + */ +CustomEvents.prototype._memorizeContext = function(ctx) { + var context, index; + + if (!isExisty(ctx)) { + return; + } + + context = this._safeContext(); + index = this._indexOfContext(ctx); + + if (index > -1) { + context[index][1] += 1; + } else { + context.push([ctx, 1]); + } +}; + +/** + * Forget supplied context object + * @param {object} ctx - context object to forget + * @private + */ +CustomEvents.prototype._forgetContext = function(ctx) { + var context, contextIndex; + + if (!isExisty(ctx)) { + return; + } + + context = this._safeContext(); + contextIndex = this._indexOfContext(ctx); + + if (contextIndex > -1) { + context[contextIndex][1] -= 1; + + if (context[contextIndex][1] <= 0) { + context.splice(contextIndex, 1); + } + } +}; + +/** + * Bind event handler + * @param {(string|{name:string, handler:function})} eventName - custom + * event name or an object {eventName: handler} + * @param {(function|object)} [handler] - handler function or context + * @param {object} [context] - context for binding + * @private + */ +CustomEvents.prototype._bindEvent = function(eventName, handler, context) { + var events = this._safeEvent(eventName); + this._memorizeContext(context); + events.push(this._getHandlerItem(handler, context)); +}; + +/** + * Bind event handlers + * @param {(string|{name:string, handler:function})} eventName - custom + * event name or an object {eventName: handler} + * @param {(function|object)} [handler] - handler function or context + * @param {object} [context] - context for binding + * //-- #1. Get Module --// + * var CustomEvents = require('tui-code-snippet/customEvents/customEvents'); // node, commonjs + * + * //-- #2. Use method --// + * // # 2.1 Basic Usage + * CustomEvents.on('onload', handler); + * + * // # 2.2 With context + * CustomEvents.on('onload', handler, myObj); + * + * // # 2.3 Bind by object that name, handler pairs + * CustomEvents.on({ + * 'play': handler, + * 'pause': handler2 + * }); + * + * // # 2.4 Bind by object that name, handler pairs with context object + * CustomEvents.on({ + * 'play': handler + * }, myObj); + */ +CustomEvents.prototype.on = function(eventName, handler, context) { + var self = this; + + if (isString(eventName)) { + // [syntax 1, 2] + eventName = eventName.split(R_EVENTNAME_SPLIT); + forEach(eventName, function(name) { + self._bindEvent(name, handler, context); + }); + } else if (isObject(eventName)) { + // [syntax 3, 4] + context = handler; + forEach(eventName, function(func, name) { + self.on(name, func, context); + }); + } +}; + +/** + * Bind one-shot event handlers + * @param {(string|{name:string,handler:function})} eventName - custom + * event name or an object {eventName: handler} + * @param {function|object} [handler] - handler function or context + * @param {object} [context] - context for binding + */ +CustomEvents.prototype.once = function(eventName, handler, context) { + var self = this; + + if (isObject(eventName)) { + context = handler; + forEach(eventName, function(func, name) { + self.once(name, func, context); + }); + + return; + } + + function onceHandler() { // eslint-disable-line require-jsdoc + handler.apply(context, arguments); + self.off(eventName, onceHandler, context); + } + + this.on(eventName, onceHandler, context); +}; + +/** + * Splice supplied array by callback result + * @param {array} arr - array to splice + * @param {function} predicate - function return boolean + * @private + */ +CustomEvents.prototype._spliceMatches = function(arr, predicate) { + var i = 0; + var len; + + if (!isArray(arr)) { + return; + } + + for (len = arr.length; i < len; i += 1) { + if (predicate(arr[i]) === true) { + arr.splice(i, 1); + len -= 1; + i -= 1; + } + } +}; + +/** + * Get matcher for unbind specific handler events + * @param {function} handler - handler function + * @returns {function} handler matcher + * @private + */ +CustomEvents.prototype._matchHandler = function(handler) { + var self = this; + + return function(item) { + var needRemove = handler === item.handler; + + if (needRemove) { + self._forgetContext(item.context); + } + + return needRemove; + }; +}; + +/** + * Get matcher for unbind specific context events + * @param {object} context - context + * @returns {function} object matcher + * @private + */ +CustomEvents.prototype._matchContext = function(context) { + var self = this; + + return function(item) { + var needRemove = context === item.context; + + if (needRemove) { + self._forgetContext(item.context); + } + + return needRemove; + }; +}; + +/** + * Get matcher for unbind specific hander, context pair events + * @param {function} handler - handler function + * @param {object} context - context + * @returns {function} handler, context matcher + * @private + */ +CustomEvents.prototype._matchHandlerAndContext = function(handler, context) { + var self = this; + + return function(item) { + var matchHandler = (handler === item.handler); + var matchContext = (context === item.context); + var needRemove = (matchHandler && matchContext); + + if (needRemove) { + self._forgetContext(item.context); + } + + return needRemove; + }; +}; + +/** + * Unbind event by event name + * @param {string} eventName - custom event name to unbind + * @param {function} [handler] - handler function + * @private + */ +CustomEvents.prototype._offByEventName = function(eventName, handler) { + var self = this; + var andByHandler = isFunction(handler); + var matchHandler = self._matchHandler(handler); + + eventName = eventName.split(R_EVENTNAME_SPLIT); + + forEach(eventName, function(name) { + var handlerItems = self._safeEvent(name); + + if (andByHandler) { + self._spliceMatches(handlerItems, matchHandler); + } else { + forEach(handlerItems, function(item) { + self._forgetContext(item.context); + }); + + self.events[name] = []; + } + }); +}; + +/** + * Unbind event by handler function + * @param {function} handler - handler function + * @private + */ +CustomEvents.prototype._offByHandler = function(handler) { + var self = this; + var matchHandler = this._matchHandler(handler); + + forEach(this._safeEvent(), function(handlerItems) { + self._spliceMatches(handlerItems, matchHandler); + }); +}; + +/** + * Unbind event by object(name: handler pair object or context object) + * @param {object} obj - context or {name: handler} pair object + * @param {function} handler - handler function + * @private + */ +CustomEvents.prototype._offByObject = function(obj, handler) { + var self = this; + var matchFunc; + + if (this._indexOfContext(obj) < 0) { + forEach(obj, function(func, name) { + self.off(name, func); + }); + } else if (isString(handler)) { + matchFunc = this._matchContext(obj); + + self._spliceMatches(this._safeEvent(handler), matchFunc); + } else if (isFunction(handler)) { + matchFunc = this._matchHandlerAndContext(handler, obj); + + forEach(this._safeEvent(), function(handlerItems) { + self._spliceMatches(handlerItems, matchFunc); + }); + } else { + matchFunc = this._matchContext(obj); + + forEach(this._safeEvent(), function(handlerItems) { + self._spliceMatches(handlerItems, matchFunc); + }); + } +}; + +/** + * Unbind custom events + * @param {(string|object|function)} eventName - event name or context or + * {name: handler} pair object or handler function + * @param {(function)} handler - handler function + * @example + * //-- #1. Get Module --// + * var CustomEvents = require('tui-code-snippet/customEvents/customEvents'); // node, commonjs + * + * //-- #2. Use method --// + * // # 2.1 off by event name + * CustomEvents.off('onload'); + * + * // # 2.2 off by event name and handler + * CustomEvents.off('play', handler); + * + * // # 2.3 off by handler + * CustomEvents.off(handler); + * + * // # 2.4 off by context + * CustomEvents.off(myObj); + * + * // # 2.5 off by context and handler + * CustomEvents.off(myObj, handler); + * + * // # 2.6 off by context and event name + * CustomEvents.off(myObj, 'onload'); + * + * // # 2.7 off by an Object. that is {eventName: handler} + * CustomEvents.off({ + * 'play': handler, + * 'pause': handler2 + * }); + * + * // # 2.8 off the all events + * CustomEvents.off(); + */ +CustomEvents.prototype.off = function(eventName, handler) { + if (isString(eventName)) { + // [syntax 1, 2] + this._offByEventName(eventName, handler); + } else if (!arguments.length) { + // [syntax 8] + this.events = {}; + this.contexts = []; + } else if (isFunction(eventName)) { + // [syntax 3] + this._offByHandler(eventName); + } else if (isObject(eventName)) { + // [syntax 4, 5, 6] + this._offByObject(eventName, handler); + } +}; + +/** + * Fire custom event + * @param {string} eventName - name of custom event + */ +CustomEvents.prototype.fire = function(eventName) { // eslint-disable-line + this.invoke.apply(this, arguments); +}; + +/** + * Fire a event and returns the result of operation 'boolean AND' with all + * listener's results. + * + * So, It is different from {@link CustomEvents#fire}. + * + * In service code, use this as a before event in component level usually + * for notifying that the event is cancelable. + * @param {string} eventName - Custom event name + * @param {...*} data - Data for event + * @returns {boolean} The result of operation 'boolean AND' + * @example + * var map = new Map(); + * map.on({ + * 'beforeZoom': function() { + * // It should cancel the 'zoom' event by some conditions. + * if (that.disabled && this.getState()) { + * return false; + * } + * return true; + * } + * }); + * + * if (this.invoke('beforeZoom')) { // check the result of 'beforeZoom' + * // if true, + * // doSomething + * } + */ +CustomEvents.prototype.invoke = function(eventName) { + var events, args, index, item; + + if (!this.hasListener(eventName)) { + return true; + } + + events = this._safeEvent(eventName); + args = Array.prototype.slice.call(arguments, 1); + index = 0; + + while (events[index]) { + item = events[index]; + + if (item.handler.apply(item.context, args) === false) { + return false; + } + + index += 1; + } + + return true; +}; + +/** + * Return whether at least one of the handlers is registered in the given + * event name. + * @param {string} eventName - Custom event name + * @returns {boolean} Is there at least one handler in event name? + */ +CustomEvents.prototype.hasListener = function(eventName) { + return this.getListenerLength(eventName) > 0; +}; + +/** + * Return a count of events registered. + * @param {string} eventName - Custom event name + * @returns {number} number of event + */ +CustomEvents.prototype.getListenerLength = function(eventName) { + var events = this._safeEvent(eventName); + + return events.length; +}; + +module.exports = CustomEvents; + + +/***/ }), +/* 59 */ +/***/ (function(module, exports) { + +var g; + +// This works in non-strict mode +g = (function() { + return this; +})(); + +try { + // This works if eval is allowed (see CSP) + g = g || new Function("return this")(); +} catch (e) { + // This works if the window reference is available + if (typeof window === "object") g = window; +} + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + +module.exports = g; + + +/***/ }), +/* 60 */, +/* 61 */, +/* 62 */, +/* 63 */, +/* 64 */, +/* 65 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +// ESM COMPAT FLAG +__webpack_require__.r(__webpack_exports__); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/collection/forEachOwnProperties.js +var forEachOwnProperties = __webpack_require__(10); +var forEachOwnProperties_default = /*#__PURE__*/__webpack_require__.n(forEachOwnProperties); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/type/isExisty.js +var isExisty = __webpack_require__(28); +var isExisty_default = /*#__PURE__*/__webpack_require__.n(isExisty); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/type/isNumber.js +var isNumber = __webpack_require__(34); +var isNumber_default = /*#__PURE__*/__webpack_require__.n(isNumber); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/object/extend.js +var extend = __webpack_require__(7); +var extend_default = /*#__PURE__*/__webpack_require__.n(extend); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/domUtil/css.js +var css = __webpack_require__(4); +var css_default = /*#__PURE__*/__webpack_require__.n(css); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/domUtil/addClass.js +var addClass = __webpack_require__(5); +var addClass_default = /*#__PURE__*/__webpack_require__.n(addClass); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/domUtil/removeClass.js +var removeClass = __webpack_require__(6); +var removeClass_default = /*#__PURE__*/__webpack_require__.n(removeClass); + +// EXTERNAL MODULE: /Users/nhn/project/tui.editor/libs/toastmark/dist/toastmark.js +var toastmark = __webpack_require__(22); + +// EXTERNAL MODULE: ./src/js/htmlRenderConvertors.js +var htmlRenderConvertors = __webpack_require__(29); + +// CONCATENATED MODULE: ./src/js/markdownToHTML.js + + +function createMarkdownToHTML(options) { + var extendedAutolinks = options.extendedAutolinks, + customHTMLRenderer = options.customHTMLRenderer, + referenceDefinition = options.referenceDefinition, + customParser = options.customParser, + frontMatter = options.frontMatter; + var parser = new toastmark["Parser"]({ + disallowedHtmlBlockTags: ['br'], + extendedAutolinks: extendedAutolinks, + referenceDefinition: referenceDefinition, + disallowDeepHeading: true, + customParser: customParser, + frontMatter: frontMatter + }); + var renderHTML = Object(toastmark["createRenderHTML"])({ + gfm: true, + convertors: Object(htmlRenderConvertors["a" /* getHTMLRenderConvertors */])(null, customHTMLRenderer) + }); + return function markdownToHTML(markdown) { + return renderHTML(parser.parse(markdown)); + }; +} +// EXTERNAL MODULE: ./src/js/utils/common.js +var utils_common = __webpack_require__(12); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/type/isBoolean.js +var isBoolean = __webpack_require__(56); +var isBoolean_default = /*#__PURE__*/__webpack_require__.n(isBoolean); + +// EXTERNAL MODULE: external {"commonjs":"codemirror","commonjs2":"codemirror","amd":"codemirror","root":["CodeMirror"]} +var external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_ = __webpack_require__(15); +var external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default = /*#__PURE__*/__webpack_require__.n(external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_); + +// CONCATENATED MODULE: ./src/js/codemirror/fixOrderedListNumber.js +/** + * @fileoverview codemirror extension for fix ordered list number + * @author NHN FE Development Lab + */ + +var listRE = /^(\s*)((\d+)([.)]\s(?:\[(?:x|\s)\]\s)?))(.*)/; +/** + * simple wrapper for indentLess command + * to run fixOrderedListNumber on Shift-Tab + * @param {CodeMirror} cm - CodeMirror instance + * @returns {CodeMirror.Pass|null} - next command + * @ignore + */ + +external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.commands.indentLessOrderedList = function (cm) { + if (cm.getOption('disableInput')) { + return external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.Pass; + } + + cm.execCommand('indentLess'); + cm.execCommand('fixOrderedListNumber'); + return null; +}; +/** + * fix ordered list number + * @param {CodeMirror} cm - CodeMirror instance + * @returns {CodeMirror.Pass|null} - next command + * @ignore + */ + + +external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.commands.fixOrderedListNumber = function (cm) { + if (cm.getOption('disableInput') || !!cm.state.isCursorInCodeBlock) { + return external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.Pass; + } + + var ranges = cm.listSelections(); + + for (var i = 0; i < ranges.length; i += 1) { + var pos = ranges[i].head; + var lineNumber = findFirstListItem(pos.line, cm); + + if (lineNumber >= 0) { + var lineText = cm.getLine(lineNumber); + + var _listRE$exec = listRE.exec(lineText), + indent = _listRE$exec[1], + index = _listRE$exec[3]; + + fixNumber(lineNumber, indent.length, parseInt(index, 10), cm); + } + } + + return null; +}; +/** + * fix list numbers + * @param {number} lineNumber - line number of list item to be normalized + * @param {number} prevIndentLength - previous indent length + * @param {number} startIndex - start index + * @param {CodeMirror} cm - CodeMirror instance + * @returns {number} - next line number + * @ignore + */ + + +function fixNumber(lineNumber, prevIndentLength, startIndex, cm) { + var indent, delimiter, text, indentLength; + var index = startIndex; + var lineText = cm.getLine(lineNumber); + + do { + var _listRE$exec2 = listRE.exec(lineText); + + indent = _listRE$exec2[1]; + delimiter = _listRE$exec2[4]; + text = _listRE$exec2[5]; + indentLength = indent.length; + + if (indentLength === prevIndentLength) { + // fix number + cm.replaceRange("" + indent + index + delimiter + text, { + line: lineNumber, + ch: 0 + }, { + line: lineNumber, + ch: lineText.length + }); + index += 1; + lineNumber += 1; + } else if (indentLength > prevIndentLength) { + // nested list start + lineNumber = fixNumber(lineNumber, indentLength, 1, cm); + } else { + // nested list end + return lineNumber; + } + + lineText = cm.getLine(lineNumber); + } while (listRE.test(lineText)); + + return lineNumber; +} +/** + * find line number of list item which contains given lineNumber + * @param {number} lineNumber - line number of list item + * @param {CodeMirror} cm - CodeMirror instance + * @returns {number} - line number of first list item + * @ignore + */ + + +function findFirstListItem(lineNumber, cm) { + var nextLineNumber = lineNumber; + var lineText = cm.getLine(lineNumber); + + while (listRE.test(lineText)) { + nextLineNumber -= 1; + lineText = cm.getLine(nextLineNumber); + } + + if (lineNumber === nextLineNumber) { + nextLineNumber = -1; + } else { + nextLineNumber += 1; + } + + return nextLineNumber; +} +// CONCATENATED MODULE: ./src/js/codemirror/overlay.js +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE +// Utility function that allows modes to be combined. The mode given +// as the base argument takes care of most of the normal mode +// functionality, but a second (typically simple) mode is used, which +// can override the style of text. Both modes get to parse all of the +// text, but when both assign a non-null style to a piece of code, the +// overlay wins, unless the combine argument was true and not overridden, +// or state.overlay.combineTokens was true, in which case the styles are +// combined. + +/** + * @modifier NHN FE Development Lab + */ + +/*eslint-disable */ + +external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.overlayMode = function (base, overlay, combine) { + return { + startState: function startState() { + return { + base: external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.startState(base), + overlay: external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.startState(overlay), + basePos: 0, + baseCur: null, + overlayPos: 0, + overlayCur: null, + streamSeen: null + }; + }, + copyState: function copyState(state) { + return { + base: external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.copyState(base, state.base), + overlay: external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.copyState(overlay, state.overlay), + basePos: state.basePos, + baseCur: null, + overlayPos: state.overlayPos, + overlayCur: null + }; + }, + token: function token(stream, state) { + if (stream != state.streamSeen || Math.min(state.basePos, state.overlayPos) < stream.start) { + state.streamSeen = stream; + state.basePos = state.overlayPos = stream.start; + } + + if (stream.start == state.basePos) { + state.baseCur = base.token(stream, state.base); + state.basePos = stream.pos; + } + + if (stream.start == state.overlayPos) { + stream.pos = stream.start; + state.overlayCur = overlay.token(stream, state.overlay); + state.overlayPos = stream.pos; + } + + stream.pos = Math.min(state.basePos, state.overlayPos); // state.overlay.combineTokens always takes precedence over combine, + // unless set to null + + if (state.overlayCur == null) return state.baseCur;else if (state.baseCur != null && state.overlay.combineTokens || combine && state.overlay.combineTokens == null) return state.baseCur + ' ' + state.overlayCur;else return state.overlayCur; + }, + indent: base.indent && function (state, textAfter) { + return base.indent(state.base, textAfter); + }, + electricChars: base.electricChars, + innerMode: function innerMode(state) { + return { + state: state.base, + mode: base + }; + }, + blankLine: function blankLine(state) { + if (base.blankLine) base.blankLine(state.base); + if (overlay.blankLine) overlay.blankLine(state.overlay); + } + }; +}; +// CONCATENATED MODULE: ./src/js/codemirror/continuelist.js +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +/** + * @modifier NHN FE Development Lab + */ + +/*eslint-disable */ + +var continuelist_listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]\s))(\s*)/, + emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/, + unorderedListRE = /[*+-]\s/; + +external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.commands.indentOrderedList = function (cm) { + if (cm.getOption('disableInput')) return external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.Pass; + var ranges = cm.listSelections(); + + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].head; + var line = cm.getLine(pos.line); + var cursorBeforeTextInline = line.substr(0, pos.ch); + + if (continuelist_listRE.test(cursorBeforeTextInline) || cm.somethingSelected()) { + cm.indentSelection('add'); + } else { + cm.execCommand('insertSoftTab'); + } + } + + cm.execCommand('fixOrderedListNumber'); +}; + +external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.commands.newlineAndIndentContinueMarkdownList = function (cm) { + if (cm.getOption('disableInput') || !!cm.state.isCursorInCodeBlock) { + cm.execCommand('newlineAndIndent'); + return; + } + + var ranges = cm.listSelections(), + replacements = []; + + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].head; + var line = cm.getLine(pos.line), + match = continuelist_listRE.exec(line); + var cursorBeforeBullet = /^\s*$/.test(line.slice(0, pos.ch)); + + if (!ranges[i].empty() || !match || cursorBeforeBullet) { + cm.execCommand('newlineAndIndent'); + return; + } + + if (emptyListRE.test(line)) { + if (!/>\s*$/.test(line)) cm.replaceRange('', { + line: pos.line, + ch: 0 + }, { + line: pos.line, + ch: pos.ch + 1 + }); + replacements[i] = '\n'; + } else { + var indent = match[1], + after = match[5]; + var numbered = !(unorderedListRE.test(match[2]) || match[2].indexOf('>') >= 0); + var bullet = numbered ? parseInt(match[3], 10) + 1 + match[4] : match[2].replace('x', ' '); + replacements[i] = '\n' + indent + bullet + after; + if (numbered) incrementRemainingMarkdownListNumbers(cm, pos); + } + } + + cm.replaceSelections(replacements); +}; // Auto-updating Markdown list numbers when a new item is added to the +// middle of a list + + +function incrementRemainingMarkdownListNumbers(cm, pos) { + var startLine = pos.line, + lookAhead = 0, + skipCount = 0; + var startItem = continuelist_listRE.exec(cm.getLine(startLine)), + startIndent = startItem[1]; + + do { + lookAhead += 1; + var nextLineNumber = startLine + lookAhead; + var nextLine = cm.getLine(nextLineNumber), + nextItem = continuelist_listRE.exec(nextLine); + + if (nextItem) { + var nextIndent = nextItem[1]; + var newNumber = parseInt(startItem[3], 10) + lookAhead - skipCount; + var nextNumber = parseInt(nextItem[3], 10), + itemNumber = nextNumber; + + if (startIndent === nextIndent && !isNaN(nextNumber)) { + if (newNumber === nextNumber) itemNumber = nextNumber + 1; + if (newNumber > nextNumber) itemNumber = newNumber + 1; + cm.replaceRange(nextLine.replace(continuelist_listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]), { + line: nextLineNumber, + ch: 0 + }, { + line: nextLineNumber, + ch: nextLine.length + }); + } else { + if (startIndent.length > nextIndent.length) return; // This doesn't run if the next line immediatley indents, as it is + // not clear of the users intention (new indented item or same level) + + if (startIndent.length < nextIndent.length && lookAhead === 1) return; + skipCount += 1; + } + } + } while (nextItem); +} +// CONCATENATED MODULE: ./src/js/codemirror/arrowKeyFunction.js +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +/** + * @modifier NHN FE Development Lab + */ + +/*eslint-disable */ + +external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.commands.replaceLineTextToUpper = function (cm) { + if (cm.getOption('disableInput')) { + return external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.Pass; + } + + var ranges = cm.listSelections(); + var lineAdjustment = -1; + + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + var from = range.anchor; + var to = range.head; + + if (isSameLineSelection(range) && to.line > 0) { + replaceSingleLine(cm, from, to, lineAdjustment); + } else if (!isRangeCollapsed(range)) { + var topLine = from.line < to.line ? from.line : to.line; + + if (topLine > 0) { + var upper = from.line === topLine ? from : to; + var bottom = from.line === topLine ? to : from; + replaceMultiLine(cm, upper, bottom, lineAdjustment); + } + } + } +}; + +external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.commands.replaceLineTextToLower = function (cm) { + if (cm.getOption('disableInput')) { + return external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.Pass; + } + + var ranges = cm.listSelections(); + var lineAdjustment = 1; + + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + var from = range.anchor; + var to = range.head; + var isLastLine = to.line === cm.lastLine(); + + if (isSameLineSelection(range) && !isLastLine) { + replaceSingleLine(cm, from, to, lineAdjustment); + } else if (!isRangeCollapsed(range)) { + var topLine = from.line < to.line ? from.line : to.line; + var upper = from.line === topLine ? from : to; + var bottom = from.line === topLine ? to : from; + + if (bottom.line < cm.lastLine()) { + replaceMultiLine(cm, upper, bottom, lineAdjustment); + } + } + } +}; + +function isRangeCollapsed(range) { + return isSameLineSelection(range) && range.anchor.ch === range.head.ch; +} + +function isSameLineSelection(range) { + return range.anchor.line === range.head.line; +} + +function replaceSingleLine(cm, from, to, lineAdjustment) { + var currentLine = cm.getLine(to.line); + var replacement = cm.getLine(to.line + lineAdjustment); + var range = { + anchor: from, + head: to + }; + cm.replaceRange(replacement, { + line: to.line, + ch: 0 + }, { + line: to.line, + ch: currentLine.length + }, '+input'); + cm.replaceRange(currentLine, { + line: to.line + lineAdjustment, + ch: 0 + }, { + line: to.line + lineAdjustment, + ch: replacement.length + }, '+input'); + + if (isRangeCollapsed(range)) { + cm.setCursor({ + line: to.line + lineAdjustment, + ch: to.ch + }); + } else { + cm.setSelection({ + line: from.line + lineAdjustment, + ch: from.ch + }, { + line: to.line + lineAdjustment, + ch: to.ch + }); + } +} + +function replaceMultiLine(cm, upper, bottom, lineAdjustment) { + var rangeContent = cm.getRange({ + line: upper.line, + ch: 0 + }, { + line: bottom.line, + ch: cm.getLine(bottom.line).length + }); + var edgeLineOfConcern = lineAdjustment > 0 ? bottom : upper; + var replacement = cm.getLine(edgeLineOfConcern.line + lineAdjustment); + var targetLine; + + if (lineAdjustment > 0) { + targetLine = upper; + } else { + targetLine = bottom; + } + + cm.replaceRange(replacement, { + line: targetLine.line, + ch: 0 + }, { + line: targetLine.line, + ch: cm.getLine(targetLine.line).length + }, '+input'); + cm.replaceRange(rangeContent, { + line: upper.line + lineAdjustment, + ch: 0 + }, { + line: bottom.line + lineAdjustment, + ch: cm.getLine(bottom.line + lineAdjustment).length + }, '+input'); + cm.setSelection({ + line: upper.line + lineAdjustment, + ch: upper.ch + }, { + line: bottom.line + lineAdjustment, + ch: bottom.ch + }); +} +// CONCATENATED MODULE: ./src/js/codemirror/placeholder.js +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +/** + * @modifier NHN FE Development Lab + */ + +/* eslint-disable */ + +external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.defineOption('placeholder', '', function (cm, val, old) { + var prev = old && old != external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.Init; + + if (val && !prev) { + cm.on('blur', onBlur); + cm.on('change', onChange); + cm.on('swapDoc', onChange); + onChange(cm); + } else if (!val && prev) { + cm.off('blur', onBlur); + cm.off('change', onChange); + cm.off('swapDoc', onChange); + clearPlaceholder(cm); + var wrapper = cm.getWrapperElement(); + wrapper.className = wrapper.className.replace(' CodeMirror-empty', ''); + } + + if (val && !cm.hasFocus()) onBlur(cm); +}); + +function clearPlaceholder(cm) { + if (cm.state.placeholder) { + cm.state.placeholder.parentNode.removeChild(cm.state.placeholder); + cm.state.placeholder = null; + } +} + +function setPlaceholder(cm) { + clearPlaceholder(cm); + var elt = cm.state.placeholder = document.createElement('pre'); + elt.style.cssText = 'height: 0; overflow: visible'; + elt.className = 'CodeMirror-placeholder'; + var placeHolder = cm.getOption('placeholder'); + if (typeof placeHolder == 'string') placeHolder = document.createTextNode(placeHolder); + elt.appendChild(placeHolder); + cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild); +} + +function onBlur(cm) { + if (isEmpty(cm)) setPlaceholder(cm); +} + +function onChange(cm) { + var wrapper = cm.getWrapperElement(), + empty = isEmpty(cm); + wrapper.className = wrapper.className.replace(' CodeMirror-empty', '') + (empty ? ' CodeMirror-empty' : ''); + if (empty) setPlaceholder(cm);else clearPlaceholder(cm); +} + +function isEmpty(cm) { + return cm.lineCount() === 1 && cm.getLine(0) === ''; +} +// CONCATENATED MODULE: ./src/js/codeMirrorExt.js +function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } + +/** + * @fileoverview Implements CodeBlockExt + * @author NHN FE Development Lab + */ + + + + + + + +/** + * Class CodeMirrorExt + * @param {HTMLElement} el - container jquery element + * @param {Object} [options={}] - codeMirror options + */ + +var codeMirrorExt_CodeMirrorExt = /*#__PURE__*/function () { + function CodeMirrorExt(el, options) { + if (options === void 0) { + options = {}; + } + + this.editorContainerEl = el; + /** + * CodeMirror instance + * @type {CodeMirror.EditorFromTextArea} + * @private + */ + + this.cm = null; + + this._init(options); + } + /** + * init + * @param {Object} options - codeMirror option + * @private + */ + + + var _proto = CodeMirrorExt.prototype; + + _proto._init = function _init(options) { + var cmTextarea = document.createElement('textarea'); + this.editorContainerEl.appendChild(cmTextarea); + options = _extends({}, options, { + lineWrapping: true, + theme: 'default', + extraKeys: _extends({ + 'Shift-Tab': 'indentLess', + 'Alt-Up': 'replaceLineTextToUpper', + 'Alt-Down': 'replaceLineTextToLower' + }, options.extraKeys), + indentUnit: 4, + cursorScrollMargin: 12, + specialCharPlaceholder: function specialCharPlaceholder() { + return document.createElement('span'); + } + }); + this.cm = external_commonjs_codemirror_commonjs2_codemirror_amd_codemirror_root_CodeMirror_default.a.fromTextArea(cmTextarea, options); + } + /** + * getCurrentRange + * @returns {Object} - selection range + */ + ; + + _proto.getCurrentRange = function getCurrentRange() { + var from = this.cm.getCursor('from'); + var to = this.cm.getCursor('to'); + return { + from: from, + to: to, + collapsed: from.line === to.line && from.ch === to.ch + }; + } + /** + * Set focus to current Editor + */ + ; + + _proto.focus = function focus() { + this.cm.focus(); + } + /** + * blur focus to current Editor + */ + ; + + _proto.blur = function blur() { + this.cm.getInputField().blur(); + } + /** + * Remove Editor from document + */ + ; + + _proto.remove = function remove() { + this.cm.toTextArea(); + } + /** + * Set Editor value + * @param {string} markdown - Markdown syntax text + * @param {boolean} [cursorToEnd=true] - move cursor to contents end + */ + ; + + _proto.setValue = function setValue(markdown, cursorToEnd) { + if (cursorToEnd === void 0) { + cursorToEnd = true; + } + + this.cm.setValue(markdown); + + if (cursorToEnd) { + this.moveCursorToEnd(); + } + + this.cm.doc.clearHistory(); + this.cm.refresh(); + } + /** + * Get editor value + * @returns {string} - codeMirror text value + */ + ; + + _proto.getValue = function getValue() { + return this.cm.getValue('\n'); + } + /** + * Get CodeMirror instance + * @returns {CodeMirror} + */ + ; + + _proto.getEditor = function getEditor() { + return this.cm; + } + /** + * Reset Editor + */ + ; + + _proto.reset = function reset() { + this.setValue(''); + } + /** + * Get current caret position + * @returns {{from: {line: number, ch: number}, to: {line: number, ch: number}}} + */ + ; + + _proto.getCaretPosition = function getCaretPosition() { + return this.cm.cursorCoords(); + } + /** + * Add widget + * @param {object} selection - Selection object + * @param {HTMLElement} node - Widget node + * @param {string} style - Adding style "over" or "bottom" + * @param {number} offset - Adding offset + */ + ; + + _proto.addWidget = function addWidget(selection, node, style, offset) { + if (offset) { + selection.ch += offset; + } + + this.cm.addWidget(selection.end, node, true, style); + } + /** + * Replace selection with given replacement content + * @param {string} content - Replacement content text + * @param {object} selection - Selection object + */ + ; + + _proto.replaceSelection = function replaceSelection(content, selection) { + if (selection) { + this.cm.setSelection(selection.from, selection.to); + } + + this.cm.replaceSelection(content); + this.focus(); + } + /** + * Replace selection with replacement content and offset + * @param {string} content - Replacement content text + * @param {number} offset - Offset + * @param {number} overwriteLength - Length to overwrite + */ + ; + + _proto.replaceRelativeOffset = function replaceRelativeOffset(content, offset, overwriteLength) { + var cursor = this.cm.getCursor(); + var selection = { + from: { + line: cursor.line, + ch: cursor.ch + offset + }, + to: { + line: cursor.line, + ch: cursor.ch + offset + overwriteLength + } + }; + this.replaceSelection(content, selection); + } + /** + * Set Editor height + * @param {number} height - Editor height + */ + ; + + _proto.setHeight = function setHeight(height) { + var contentWrapper = this.getWrapperElement(); + css_default()(contentWrapper, { + height: height + "px" + }); + } + /** + * set min height + * @param {number} minHeight - min height + */ + ; + + _proto.setMinHeight = function setMinHeight(minHeight) { + var contentWrapper = this.getWrapperElement(); + css_default()(contentWrapper, { + minHeight: minHeight + "px" + }); + } + /** + * Set the placeholder to CodeMirror + * @param {string} placeholder - placeholder to set + */ + ; + + _proto.setPlaceholder = function setPlaceholder(placeholder) { + if (placeholder) { + this.cm.setOption('placeholder', placeholder); + } + } + /** + * get code mirror wrapper element + * @returns {HTMLElement} - code mirror wrapper element + */ + ; + + _proto.getWrapperElement = function getWrapperElement() { + return this.cm.getWrapperElement(); + } + /** + * get code mirror cursor + * @param {string} [start='head'] - which end of the selection. 'from'|'to'|'head'|'anchor' + * @returns {Cursor} - code mirror cursor + */ + ; + + _proto.getCursor = function getCursor(start) { + return this.cm.getCursor(start); + } + /** + * Set cursor position to end + */ + ; + + _proto.moveCursorToEnd = function moveCursorToEnd() { + var doc = this.getEditor().getDoc(); + var lastLine = doc.lastLine(); + doc.setCursor(lastLine, doc.getLine(lastLine).length); + } + /** + * Set cursor position to start + */ + ; + + _proto.moveCursorToStart = function moveCursorToStart() { + var doc = this.getEditor().getDoc(); + var firstLine = doc.firstLine(); + doc.setCursor(firstLine, 0); + } + /** + * Scroll Editor content to Top + * @param {number} value - Scroll amount + * @returns {number} - changed scroll top + */ + ; + + _proto.scrollTop = function scrollTop(value) { + if (value) { + this.cm.scrollTo(0, value); + } + + return this.cm.getScrollInfo().top; + } + /** + * Get start, end position of current selection + * @returns {{start: {line: *, ch: *}, end: {line: *, ch: *}}} + */ + ; + + _proto.getRange = function getRange() { + var start = this.cm.getCursor('from'); + var end = this.cm.getCursor('to'); + return { + start: { + line: start.line, + ch: start.ch + }, + end: { + line: end.line, + ch: end.ch + } + }; + } + /** + * add codemirror event handler + * @param {string} type - event type + * @param {function} func - handler function + */ + ; + + _proto.on = function on(type, func) { + this.cm.on(type, func); + } + /** + * remove codemirror event handler + * @param {string} type - event type + * @param {function} func - handler function + */ + ; + + _proto.off = function off(type, func) { + this.cm.off(type, func); + }; + + return CodeMirrorExt; +}(); + +/* harmony default export */ var codeMirrorExt = (codeMirrorExt_CodeMirrorExt); +// CONCATENATED MODULE: ./src/js/keyMapper.js +/** + * @fileoverview Implements KeyMapper + * @author NHN FE Development Lab + */ + +/** + * Constant of key mapping + * @type {string[]} + * @ignore + */ +var KEYBOARD_MAP = ['', // [0] +'', // [1] +'', // [2] +'CANCEL', // [3] +'', // [4] +'', // [5] +'HELP', // [6] +'', // [7] +'BACK_SPACE', // [8] +'TAB', // [9] +'', // [10] +'', // [11] +'CLEAR', // [12] +'ENTER', // [13] +'ENTER_SPECIAL', // [14] +'', // [15] +'', // [16] SHIFT +'', // [17] CONTROL +'', // [18] ALT +'PAUSE', // [19] +'CAPS_LOCK', // [20] +'KANA', // [21] +'EISU', // [22] +'JUNJA', // [23] +'FINAL', // [24] +'HANJA', // [25] +'', // [26] +'ESCAPE', // [27] +'CONVERT', // [28] +'NONCONVERT', // [29] +'ACCEPT', // [30] +'MODECHANGE', // [31] +'SPACE', // [32] +'PAGE_UP', // [33] +'PAGE_DOWN', // [34] +'END', // [35] +'HOME', // [36] +'LEFT', // [37] +'UP', // [38] +'RIGHT', // [39] +'DOWN', // [40] +'SELECT', // [41] +'PRINT', // [42] +'EXECUTE', // [43] +'PRINTSCREEN', // [44] +'INSERT', // [45] +'DELETE', // [46] +'', // [47] +'0', // [48] +'1', // [49] +'2', // [50] +'3', // [51] +'4', // [52] +'5', // [53] +'6', // [54] +'7', // [55] +'8', // [56] +'9', // [57] +':', // [58] +';', // [59] +'<', // [60] +'=', // [61] +'>', // [62] +'?', // [63] +'AT', // [64] +'A', // [65] +'B', // [66] +'C', // [67] +'D', // [68] +'E', // [69] +'F', // [70] +'G', // [71] +'H', // [72] +'I', // [73] +'J', // [74] +'K', // [75] +'L', // [76] +'M', // [77] +'N', // [78] +'O', // [79] +'P', // [80] +'Q', // [81] +'R', // [82] +'S', // [83] +'T', // [84] +'U', // [85] +'V', // [86] +'W', // [87] +'X', // [88] +'Y', // [89] +'Z', // [90] +'', // [91] META +'', // [92] +'CONTEXT_MENU', // [93] +'', // [94] +'SLEEP', // [95] +'NUMPAD0', // [96] +'NUMPAD1', // [97] +'NUMPAD2', // [98] +'NUMPAD3', // [99] +'NUMPAD4', // [100] +'NUMPAD5', // [101] +'NUMPAD6', // [102] +'NUMPAD7', // [103] +'NUMPAD8', // [104] +'NUMPAD9', // [105] +'MULTIPLY', // [106] +'ADD', // [107] +'SEPARATOR', // [108] +'SUBTRACT', // [109] +'DECIMAL', // [110] +'DIVIDE', // [111] +'F1', // [112] +'F2', // [113] +'F3', // [114] +'F4', // [115] +'F5', // [116] +'F6', // [117] +'F7', // [118] +'F8', // [119] +'F9', // [120] +'F10', // [121] +'F11', // [122] +'F12', // [123] +'F13', // [124] +'F14', // [125] +'F15', // [126] +'F16', // [127] +'F17', // [128] +'F18', // [129] +'F19', // [130] +'F20', // [131] +'F21', // [132] +'F22', // [133] +'F23', // [134] +'F24', // [135] +'', // [136] +'', // [137] +'', // [138] +'', // [139] +'', // [140] +'', // [141] +'', // [142] +'', // [143] +'NUM_LOCK', // [144] +'SCROLL_LOCK', // [145] +'WIN_OEM_FJ_JISHO', // [146] +'WIN_OEM_FJ_MASSHOU', // [147] +'WIN_OEM_FJ_TOUROKU', // [148] +'WIN_OEM_FJ_LOYA', // [149] +'WIN_OEM_FJ_ROYA', // [150] +'', // [151] +'', // [152] +'', // [153] +'', // [154] +'', // [155] +'', // [156] +'', // [157] +'', // [158] +'', // [159] +'@', // [160] +'!', // [161] +'"', // [162] +'#', // [163] +'$', // [164] +'%', // [165] +'&', // [166] +'_', // [167] +'(', // [168] +')', // [169] +'*', // [170] +'+', // [171] +'|', // [172] +'-', // [173] +'{', // [174] +'}', // [175] +'~', // [176] +'', // [177] +'', // [178] +'', // [179] +'', // [180] +'VOLUME_MUTE', // [181] +'VOLUME_DOWN', // [182] +'VOLUME_UP', // [183] +'', // [184] +'', // [185] +';', // [186] +'=', // [187] +',', // [188] +'-', // [189] +'.', // [190] +'/', // [191] +'`', // [192] +'', // [193] +'', // [194] +'', // [195] +'', // [196] +'', // [197] +'', // [198] +'', // [199] +'', // [200] +'', // [201] +'', // [202] +'', // [203] +'', // [204] +'', // [205] +'', // [206] +'', // [207] +'', // [208] +'', // [209] +'', // [210] +'', // [211] +'', // [212] +'', // [213] +'', // [214] +'', // [215] +'', // [216] +'', // [217] +'', // [218] +'[', // [219] +'\\', // [220] +']', // [221] +"'", // [222] +'', // [223] +'META', // [224] +'ALTGR', // [225] +'', // [226] +'WIN_ICO_HELP', // [227] +'WIN_ICO_00', // [228] +'', // [229] +'WIN_ICO_CLEAR', // [230] +'', // [231] +'', // [232] +'WIN_OEM_RESET', // [233] +'WIN_OEM_JUMP', // [234] +'WIN_OEM_PA1', // [235] +'WIN_OEM_PA2', // [236] +'WIN_OEM_PA3', // [237] +'WIN_OEM_WSCTRL', // [238] +'WIN_OEM_CUSEL', // [239] +'WIN_OEM_ATTN', // [240] +'WIN_OEM_FINISH', // [241] +'WIN_OEM_COPY', // [242] +'WIN_OEM_AUTO', // [243] +'WIN_OEM_ENLW', // [244] +'WIN_OEM_BACKTAB', // [245] +'ATTN', // [246] +'CRSEL', // [247] +'EXSEL', // [248] +'EREOF', // [249] +'PLAY', // [250] +'ZOOM', // [251] +'', // [252] +'PA1', // [253] +'WIN_OEM_CLEAR', // [254] +'' // [255] +]; +var sharedInstance; +/** + * Class KeyMapper + * @param {object} [options] options + * @param {string} options.splitter splitter string default is + + * @ignore + */ + +var KeyMapper = /*#__PURE__*/function () { + function KeyMapper(options) { + this._setSplitter(options); + } + /** + * Set key splitter + * @param {object} options Option object + * @private + */ + + + var _proto = KeyMapper.prototype; + + _proto._setSplitter = function _setSplitter(options) { + var splitter = options ? options.splitter : '+'; + this._splitter = splitter; + } + /** + * Convert event to keyMap + * @param {event} event Event object + * @returns {string} + */ + ; + + _proto.convert = function convert(event) { + var keyMap = []; + + if (event.shiftKey) { + keyMap.push('SHIFT'); + } + + if (event.ctrlKey) { + keyMap.push('CTRL'); + } + + if (event.metaKey) { + keyMap.push('META'); + } + + if (event.altKey) { + keyMap.push('ALT'); + } + + var keyChar = this._getKeyCodeChar(event.keyCode); + + if (keyChar) { + keyMap.push(keyChar); + } + + return keyMap.join(this._splitter); + } + /** + * Get character from key code + * @param {number} keyCode Key code + * @returns {string} + * @private + */ + ; + + _proto._getKeyCodeChar = function _getKeyCodeChar(keyCode) { + var keyCodeCharacter = KEYBOARD_MAP[keyCode]; + return keyCodeCharacter; + } + /** + * Get sharedInstance + * @returns {KeyMapper} + */ + ; + + KeyMapper.getSharedInstance = function getSharedInstance() { + if (!sharedInstance) { + sharedInstance = new KeyMapper(); + } + + return sharedInstance; + } + /** + * get key code for a character + * @param {string} char - a character to be converted + * @returns {number} key code for the char + * @static + */ + ; + + KeyMapper.keyCode = function keyCode(char) { + return KEYBOARD_MAP.indexOf(char); + }; + + return KeyMapper; +}(); + +/* harmony default export */ var keyMapper = (KeyMapper); +// CONCATENATED MODULE: ./src/js/mdListManager.js +/** + * @fileoverview Implements markdown list manager + * @author NHN FE Development Lab + */ +var FIND_LIST_RX = /^[ \t]*([-*]|[\d]+\.)( \[[ xX]])? /; +var FIND_TASK_LIST_RX = /^[ \t]*([*-] |[\d]+\. )(\[[ xX]] )/; +var FIND_UL_RX = /^[ \t]*[-*] .*/; +var FIND_OL_TASK_RX = /^[ \t]*[\d]+\. \[[ xX]] .*/; +var LIST_SYNTAX_RX = /([*-] |[\d]+\. )/; +var TASK_SYNTAX_RX = /([-*] |[\d]+\. )(\[[ xX]] )/; +var LIST_OR_TASK_SYNTAX_RX = /([-*]|[\d]+\.)( \[[ xX]])? /; +var UL_TASK_SYNTAX_RX = /([-*])( \[[ xX]]) /; +var OL_SYNTAX_RX = /([\d])+\.( \[[ xX]])? /; +var FIND_TABLE_RX = /^\|([-\s\w\d\t<>?!@#$%^&*()_=+\\/'";: \r[\]]*\|+)+/i; +var FIND_HEADING_RX = /^#+\s/; +var FIND_BLOCK_RX = /^ {0,3}(```|\||>)/; +/** + * Class MdListManager + * @param {MarkdownEditor} mde - MarkdownEditor instance + * @ignore + */ + +var MdListManager = /*#__PURE__*/function () { + function MdListManager(mde) { + this.cm = mde.getEditor(); + this.doc = this.cm.getDoc(); + this.toastMark = mde.getToastMark(); + /** + * Name property + * @type {string} + */ + + this.name = 'list'; + } + /** + * Sort line number of selection descending + * @param {{from, to}} range start, end CodeMirror range information + * @returns {{start: {number}, end: {number}}} + * @private + */ + + + var _proto = MdListManager.prototype; + + _proto._createSortedLineRange = function _createSortedLineRange(range) { + var isReversed = range.from.line > range.to.line; + var rangeStart = { + line: isReversed ? range.to.line : range.from.line, + ch: 0 + }; + var rangeEnd = { + line: isReversed ? range.from.line : range.to.line, + ch: 0 + }; + return { + start: rangeStart.line, + end: rangeEnd.line + }; + } + /** + * For odering the ol list, search preivous lines and + * calculate ordinal number when find ol list + * @param {number} lineNumber lineNumber + * @returns {number} + * @private + */ + ; + + _proto._calculateOrdinalNumber = function _calculateOrdinalNumber(lineNumber) { + var ordinalNumber = 1; + + for (var i = lineNumber - 1; i >= 0; i -= 1) { + var depth = this._getListDepth(i); + + if (depth === 1 && OL_SYNTAX_RX.exec(this.doc.getLine(i))) { + ordinalNumber = parseInt(RegExp.$1, 10) + 1; + break; + } else if (depth === 0) { + break; + } + } + + return ordinalNumber; + }; + + _proto._isListLine = function _isListLine(lineNumber) { + return !!FIND_LIST_RX.exec(this.doc.getLine(lineNumber)); + } + /** + * If text already have sytax for heading, table and code block, + * can not change to list. + * @param {number} lineNumber lineNumber + * @returns {boolean} + * @private + */ + ; + + _proto._isCanBeList = function _isCanBeList(lineNumber) { + var line = this.doc.getLine(lineNumber); + return !FIND_BLOCK_RX.test(line) && !FIND_TABLE_RX.test(line) && !FIND_HEADING_RX.test(line); + } + /** + * Return a function for change according to type + * @param {string} type ol, ul, task + * @returns {Function} + * @private + */ + ; + + _proto._getChangeFn = function _getChangeFn(type) { + var _this = this; + + var fn; + + switch (type) { + case 'ol': + case 'ul': + fn = function fn(lineNumber) { + return _this._changeToList(lineNumber, type); + }; + + break; + + case 'task': + fn = function fn(lineNumber) { + return _this._changeToTask(lineNumber); + }; + + break; + + default: + break; + } + + return fn; + } + /** + * Change syntax by traversing each line selected. + * @param {{from, to}} range start, end CodeMirror range information + * @param {string} type ol, ul, task + */ + ; + + _proto.changeSyntax = function changeSyntax(range, type) { + var newListLine = []; + + var lineRange = this._createSortedLineRange(range); + + var startLineNumber = lineRange.start, + endLineNumber = lineRange.end; + + var changeFn = this._getChangeFn(type); + + for (var lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber += 1) { + if (!this._isCanBeList(lineNumber)) { + break; + } // If text of lineNumber is not list, cache for inserting blank line + + + if (!this._isListLine(lineNumber)) { + newListLine.push(lineNumber); + } + + changeFn(lineNumber); + } // Should insert blank line before and after new list + + + this._insertBlankLineForNewList(newListLine); + + this.cm.focus(); + }; + + _proto._replaceLineText = function _replaceLineText(text, lineNumber) { + this.doc.replaceRange(text, { + line: lineNumber, + ch: 0 + }); + } + /** + * change to list according to the type. + * @param {number} lineNumber line number + * @param {string} type ol, ul + * @private + */ + ; + + _proto._changeToList = function _changeToList(lineNumber, type) { + var _this2 = this; + + if (this._isListLine(lineNumber)) { + // If type is ol, need ordinal number. + this._changeSameDepthList(lineNumber, type === 'ol' ? function (lineNum, ordinalNumber) { + _this2._replaceListTypeToOL(lineNum, ordinalNumber); + } : function (lineNum) { + _this2._replaceListTypeToUL(lineNum); + }); + } else { + this._replaceLineText(type === 'ol' ? this._calculateOrdinalNumber(lineNumber) + ". " : '* ', lineNumber); + } + } + /** + * change to task list according + * @param {number} lineNumber line number + * @private + */ + ; + + _proto._changeToTask = function _changeToTask(lineNumber) { + if (FIND_TASK_LIST_RX.exec(this.doc.getLine(lineNumber))) { + this._replaceLineTextByRegexp(lineNumber, TASK_SYNTAX_RX, '$1'); + } else if (this._isListLine(lineNumber)) { + this._replaceLineTextByRegexp(lineNumber, LIST_SYNTAX_RX, '$1[ ] '); + } else { + this._replaceLineText('* [ ] ', lineNumber); + } + }; + + _proto._getListDepth = function _getListDepth(lineNumber) { + var depth = 0; + var text = this.doc.getLine(lineNumber); + + if (text) { + var mdNode = this.toastMark.findFirstNodeAtLine(lineNumber + 1); + + while (mdNode && mdNode.type !== 'document') { + if (mdNode.type === 'list') { + depth += 1; + } + + mdNode = mdNode.parent; + } + } + + return depth; + }; + + _proto._findSameDepthList = function _findSameDepthList(listNumber, depth, isIncrease) { + var lineCount = this.doc.lineCount(); + var result = []; + var i = listNumber; + var currentLineDepth; + + while (isIncrease ? i < lineCount - 1 : i > 0) { + i = isIncrease ? i + 1 : i - 1; + currentLineDepth = this._getListDepth(i); + + if (currentLineDepth === depth) { + result.push(i); + } else if (currentLineDepth < depth) { + break; + } + } + + return result; + } + /** + * Find Sampe depth list before and after the line number, + * and then same depth lines change using replacer function + * @param {number} lineNumber line number + * @param {Function} replacer The function should be called with line numbers and ordinal number as arguments. + * @private + */ + ; + + _proto._changeSameDepthList = function _changeSameDepthList(lineNumber, replacer) { + var depth = this._getListDepth(lineNumber); + + var backwardList = this._findSameDepthList(lineNumber, depth, false).reverse(); + + var forwardList = this._findSameDepthList(lineNumber, depth, true); + + var sameDepthList = backwardList.concat([lineNumber]).concat(forwardList); + sameDepthList.forEach(function (lineNum, i) { + replacer(lineNum, i + 1); + }); + } + /** + * Replace text using regular expression + * @param {number} lineNumber Line number + * @param {RegExp} regexp Regexp for find list syntax + * @param {string} replacePattern Replacement string + * @private + */ + ; + + _proto._replaceLineTextByRegexp = function _replaceLineTextByRegexp(lineNumber, regexp, replacePattern) { + var line = this.doc.getLine(lineNumber); + var currentLineStart = { + line: lineNumber, + ch: 0 + }; + var currentLineEnd = { + line: lineNumber, + ch: line.length + }; + line = line.replace(regexp, replacePattern); + this.doc.replaceRange(line, currentLineStart, currentLineEnd); + }; + + _proto._replaceListTypeToUL = function _replaceListTypeToUL(lineNumber) { + var lineText = this.doc.getLine(lineNumber); + + if (UL_TASK_SYNTAX_RX.exec(lineText)) { + this._replaceLineTextByRegexp(lineNumber, UL_TASK_SYNTAX_RX, '$1 '); + } else if (OL_SYNTAX_RX.exec(lineText)) { + this._replaceLineTextByRegexp(lineNumber, OL_SYNTAX_RX, '* '); + } + }; + + _proto._replaceListTypeToOL = function _replaceListTypeToOL(lineNumber, ordinalNumber) { + var lineText = this.doc.getLine(lineNumber); + + if (FIND_UL_RX.exec(lineText) || FIND_OL_TASK_RX.exec(lineText)) { + this._replaceLineTextByRegexp(lineNumber, LIST_OR_TASK_SYNTAX_RX, ordinalNumber + ". "); + } else if (OL_SYNTAX_RX.exec(lineText)) { + if (parseInt(RegExp.$1, 10) !== ordinalNumber) { + this._replaceLineTextByRegexp(lineNumber, OL_SYNTAX_RX, ordinalNumber + ". "); + } + } + } + /** + * The new list must have a blank line before and after. + * @param {Array} newListLines lines that changed to list + * @private + */ + ; + + _proto._insertBlankLineForNewList = function _insertBlankLineForNewList(newListLines) { + var length = newListLines.length; + + if (length) { + var startLineNumber = newListLines[0]; + var endLineNumber = newListLines[length - 1]; + + if (this._isNotBlankNotListLine(endLineNumber + 1)) { + this.doc.replaceRange('\n', { + line: endLineNumber, + ch: this.doc.getLine(endLineNumber).length + }); + } + + if (startLineNumber > 0 && this._isNotBlankNotListLine(startLineNumber - 1)) { + this.doc.replaceRange('\n', { + line: startLineNumber, + ch: 0 + }); + } + } + }; + + _proto._isNotBlankNotListLine = function _isNotBlankNotListLine(lineNumber) { + return !!this.doc.getLine(lineNumber) && !this._isListLine(lineNumber); + }; + + return MdListManager; +}(); + +/* harmony default export */ var mdListManager = (MdListManager); +// CONCATENATED MODULE: ./src/js/componentManager.js +/** + * @fileoverview Implements ComponentManager + * @author NHN FE Development Lab + */ + +/** + * Class ComponentManager + * @param {MarkdownEditor|WysiwygEditor} editor - Editor instance + * @ignore + */ +var ComponentManager = /*#__PURE__*/function () { + function ComponentManager(editor) { + /** + * private + * @type {object} + * @private + */ + this._managers = {}; + this._editor = editor; + } + /** + * addManager + * Add manager + * @param {string|function} nameOrConstructor Manager name or constructor + * @param {function} [ManagerConstructor] Constructor + */ + + + var _proto = ComponentManager.prototype; + + _proto.addManager = function addManager(nameOrConstructor, ManagerConstructor) { + if (!ManagerConstructor) { + ManagerConstructor = nameOrConstructor; + nameOrConstructor = null; + } + + var instance = new ManagerConstructor(this._editor); + this._managers[nameOrConstructor || instance.name] = instance; + } + /** + * getManager + * Get manager by manager name + * @param {string} name Manager name + * @returns {object} manager + */ + ; + + _proto.getManager = function getManager(name) { + return this._managers[name]; + } + /** + * Remove Manager. + * @param {string} name - manager name + */ + ; + + _proto.removeManager = function removeManager(name) { + var manager = this.getManager(name); + + if (!manager) { + return; + } + + if (manager.destroy) { + manager.destroy(); + } + + delete this._managers[name]; + }; + + return ComponentManager; +}(); + +/* harmony default export */ var componentManager = (ComponentManager); +// CONCATENATED MODULE: ./src/js/mdTextObject.js +/** + * @fileoverview Implements markdown textObject + * @author NHN FE Development Lab + */ + +/** + * Class Markdown textObject + * @param {MarkdownEditor} mde - MarkdownEditor instance + * @param {object} range - range + */ +var MdTextObject = /*#__PURE__*/function () { + function MdTextObject(mde, range) { + this._mde = mde; + this.setRange(range || mde.getRange()); + } + /** + * Set start + * @param {object} rangeStart Start of range + * @private + */ + + + var _proto = MdTextObject.prototype; + + _proto._setStart = function _setStart(rangeStart) { + this._start = rangeStart; + } + /** + * Set end + * @param {object} rangeEnd End of range + * @private + */ + ; + + _proto._setEnd = function _setEnd(rangeEnd) { + this._end = rangeEnd; + } + /** + * Set range to given range + * @param {object} range Range object + */ + ; + + _proto.setRange = function setRange(range) { + this._setStart(range.start); + + this._setEnd(range.end); + } + /** + * Set start to end + * @param {object} range Range object + */ + ; + + _proto.setEndBeforeRange = function setEndBeforeRange(range) { + this._setEnd(range.start); + } + /** + * Expand startOffset by 1 + */ + ; + + _proto.expandStartOffset = function expandStartOffset() { + var start = this._start; + + if (start.ch !== 0) { + start.ch -= 1; + } + } + /** + * Expand endOffset by 1 + */ + ; + + _proto.expandEndOffset = function expandEndOffset() { + var end = this._end; + + if (end.ch < this._mde.getEditor().getDoc().getLine(end.line).length) { + end.ch += 1; + } + } + /** + * Get current selection's text content + * @returns {{start: {line: number, ch: number}, end: {line: number, ch: number}}} + */ + ; + + _proto.getTextContent = function getTextContent() { + return this._mde.getEditor().getRange(this._start, this._end); + } + /** + * Replace current selection's content with given text content + * @param {string} content Replacement content + */ + ; + + _proto.replaceContent = function replaceContent(content) { + this._mde.getEditor().replaceRange(content, this._start, this._end, '+input'); + } + /** + * Delete current selection's content + */ + ; + + _proto.deleteContent = function deleteContent() { + this._mde.getEditor().replaceRange('', this._start, this._end, '+delete'); + } + /** + * peek StartBeforeOffset + * @param {number} offset Offset + * @returns {{start: {line: number, ch: number}, end: {line: number, ch: number}}} + */ + ; + + _proto.peekStartBeforeOffset = function peekStartBeforeOffset(offset) { + var peekStart = { + line: this._start.line, + ch: Math.max(this._start.ch - offset, 0) + }; + return this._mde.getEditor().getRange(peekStart, this._start); + }; + + return MdTextObject; +}(); + +/* harmony default export */ var mdTextObject = (MdTextObject); +// EXTERNAL MODULE: ./src/js/utils/markdown.js +var markdown = __webpack_require__(2); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/type/isFunction.js +var isFunction = __webpack_require__(27); +var isFunction_default = /*#__PURE__*/__webpack_require__.n(isFunction); + +// CONCATENATED MODULE: ./src/js/markTextHelper.js +function markTextHelper_extends() { markTextHelper_extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return markTextHelper_extends.apply(this, arguments); } + + + + +var CLS_PREFIX = 'tui-md-'; +var classNameMap = applyClsToValue({ + DELIM: 'delimiter', + META: 'meta', + TEXT: 'marked-text', + THEMATIC_BREAK: 'thematic-break', + CODE_BLOCK: 'code-block', + TABLE: 'table', + HTML: 'html' +}); +var delimSize = { + strong: 2, + emph: 1, + strike: 2 +}; + +function cls() { + for (var _len = arguments.length, names = new Array(_len), _key = 0; _key < _len; _key++) { + names[_key] = arguments[_key]; + } + + return names.map(function (className) { + return "" + CLS_PREFIX + className; + }).join(' '); +} + +function applyClsToValue(obj) { + forEachOwnProperties_default()(obj, function (value, key) { + obj[key] = cls(value); + }); + return obj; +} + +function markTextHelper_markInfo(start, end, className) { + return { + start: start, + end: end, + className: className + }; +} + +function heading(_ref, start, end) { + var level = _ref.level, + headingType = _ref.headingType; + var marks = [markTextHelper_markInfo(start, end, cls('heading', "heading" + level))]; + + if (headingType === 'atx') { + marks.push(markTextHelper_markInfo(start, Object(markdown["a" /* addChPos */])(start, level), classNameMap.DELIM)); + } else { + marks.push(markTextHelper_markInfo(Object(markdown["m" /* setChPos */])(end, 0), end, classNameMap.DELIM + " setext")); + } + + return { + marks: marks + }; +} + +function emphasisAndStrikethrough(_ref2, start, end) { + var type = _ref2.type; + return { + marks: [markTextHelper_markInfo(start, end, cls("" + type)), markTextHelper_markInfo(start, Object(markdown["a" /* addChPos */])(start, delimSize[type]), classNameMap.DELIM), markTextHelper_markInfo(Object(markdown["a" /* addChPos */])(end, -delimSize[type]), end, classNameMap.DELIM)] + }; +} + +function markLink(start, end, linkTextStart, lastChildCh) { + return [markTextHelper_markInfo(start, end, cls('link')), markTextHelper_markInfo(linkTextStart, Object(markdown["m" /* setChPos */])(end, lastChildCh), cls('link-desc')), markTextHelper_markInfo(Object(markdown["m" /* setChPos */])(start, linkTextStart.ch + 1), Object(markdown["m" /* setChPos */])(end, lastChildCh - 1), classNameMap.TEXT), markTextHelper_markInfo(Object(markdown["m" /* setChPos */])(end, lastChildCh), end, cls('link-url')), markTextHelper_markInfo(Object(markdown["m" /* setChPos */])(end, lastChildCh + 1), Object(markdown["a" /* addChPos */])(end, -1), classNameMap.TEXT)]; +} + +function markTextHelper_image(_ref3, start, end) { + var lastChild = _ref3.lastChild; + var lastChildCh = lastChild ? Object(markdown["c" /* getMdEndCh */])(lastChild) + 1 : 3; // 3: length of '![]' + + var linkTextEnd = Object(markdown["a" /* addChPos */])(start, 1); + return { + marks: [markTextHelper_markInfo(start, linkTextEnd, classNameMap.META)].concat(markLink(start, end, linkTextEnd, lastChildCh)) + }; +} + +function markTextHelper_link(_ref4, start, end) { + var lastChild = _ref4.lastChild, + extendedAutolink = _ref4.extendedAutolink; + var lastChildCh = lastChild ? Object(markdown["c" /* getMdEndCh */])(lastChild) + 1 : 2; // 2: length of '[]' + + var marks = extendedAutolink ? [markTextHelper_markInfo(start, end, cls('link', 'link-desc') + " " + classNameMap.TEXT)] : markLink(start, end, start, lastChildCh); + return { + marks: marks + }; +} + +function markTextHelper_code(_ref5, start, end) { + var tickCount = _ref5.tickCount; + var openDelimEnd = Object(markdown["a" /* addChPos */])(start, tickCount); + var closeDelimStart = Object(markdown["a" /* addChPos */])(end, -tickCount); + return { + marks: [markTextHelper_markInfo(start, end, cls('code')), markTextHelper_markInfo(start, openDelimEnd, classNameMap.DELIM + " start"), markTextHelper_markInfo(openDelimEnd, closeDelimStart, classNameMap.TEXT), markTextHelper_markInfo(closeDelimStart, end, classNameMap.DELIM + " end")] + }; +} + +function markTextHelper_codeBlock(node, start, end, endLine) { + var fenceOffset = node.fenceOffset, + fenceLength = node.fenceLength, + fenceChar = node.fenceChar, + info = node.info, + infoPadding = node.infoPadding, + parent = node.parent; + var fenceEnd = fenceOffset + fenceLength; + var marks = [markTextHelper_markInfo(Object(markdown["m" /* setChPos */])(start, 0), end, classNameMap.CODE_BLOCK)]; + + if (fenceChar) { + marks.push(markTextHelper_markInfo(start, Object(markdown["a" /* addChPos */])(start, fenceEnd), classNameMap.DELIM)); + } + + if (info) { + marks.push(markTextHelper_markInfo(Object(markdown["m" /* setChPos */])(start, fenceEnd), Object(markdown["m" /* setChPos */])(start, fenceEnd + infoPadding + info.length), classNameMap.META)); + } + + var codeBlockEnd = "^(\\s{0,3})(" + fenceChar + "{" + fenceLength + ",})"; + var CLOSED_RX = new RegExp(codeBlockEnd); + + if (CLOSED_RX.test(endLine)) { + marks.push(markTextHelper_markInfo(Object(markdown["m" /* setChPos */])(end, 0), end, classNameMap.DELIM)); + } + + var lineBackground = parent.type !== 'item' && parent.type !== 'blockQuote' ? { + start: start.line, + end: end.line, + className: classNameMap.CODE_BLOCK + } : null; + return { + marks: marks, + lineBackground: markTextHelper_extends({}, lineBackground) + }; +} + +function markListItemChildren(node, className) { + var marks = []; + + while (node) { + var _node = node, + type = _node.type; + + if (type === 'paragraph' || type === 'codeBlock') { + marks.push(markTextHelper_markInfo({ + line: Object(markdown["f" /* getMdStartLine */])(node) - 1, + ch: Object(markdown["e" /* getMdStartCh */])(node) - 1 + }, { + line: Object(markdown["d" /* getMdEndLine */])(node) - 1, + ch: Object(markdown["c" /* getMdEndCh */])(node) + }, className)); + } + + node = node.next; + } + + return marks; +} + +function markParagraphInBlockQuote(node) { + var marks = []; + + while (node) { + marks.push(markTextHelper_markInfo({ + line: Object(markdown["f" /* getMdStartLine */])(node) - 1, + ch: Object(markdown["e" /* getMdStartCh */])(node) - 1 + }, { + line: Object(markdown["d" /* getMdEndLine */])(node) - 1, + ch: Object(markdown["c" /* getMdEndCh */])(node) + }, classNameMap.TEXT)); + node = node.next; + } + + return marks; +} + +function blockQuote(node, start, end) { + var marks = node.parent && node.parent.type !== 'blockQuote' ? [markTextHelper_markInfo(start, end, cls('block-quote'))] : []; + + if (node.firstChild) { + var childMarks = []; + + if (node.firstChild.type === 'paragraph') { + childMarks = markParagraphInBlockQuote(node.firstChild.firstChild, classNameMap.TEXT); + } else if (node.firstChild.type === 'list') { + childMarks = markListItemChildren(node.firstChild, classNameMap.TEXT); + } + + marks = [].concat(marks, childMarks); + } + + return { + marks: marks + }; +} + +function getClassNameOfListItem(node) { + var depth = 0; + + while (node.parent.parent && node.parent.parent.type === 'item') { + node = node.parent.parent; + depth += 1; + } + + var newClassName = ['list-item-odd', 'list-item-even'][depth % 2]; // @TODO remove it in the next major version + // these class names are for the legacy style 'old.css' + + var oldClassName = ['fisrt', 'second', 'third'][depth % 3]; + return cls('list-item', "" + newClassName) + " " + oldClassName; +} + +function markTextHelper_item(node, start) { + var itemClassName = getClassNameOfListItem(node); + var _node$listData = node.listData, + padding = _node$listData.padding, + task = _node$listData.task; + return { + marks: [markTextHelper_markInfo(start, Object(markdown["a" /* addChPos */])(start, padding), itemClassName + " " + cls('list-item-bullet'))].concat(task ? [markTextHelper_markInfo(Object(markdown["a" /* addChPos */])(start, padding), Object(markdown["a" /* addChPos */])(start, padding + 3), itemClassName + " " + classNameMap.DELIM), markTextHelper_markInfo(Object(markdown["a" /* addChPos */])(start, padding + 1), Object(markdown["a" /* addChPos */])(start, padding + 2), classNameMap.META)] : [], markListItemChildren(node.firstChild, itemClassName + " " + classNameMap.TEXT)) + }; +} + +var markNodeFuncMap = { + heading: heading, + strong: emphasisAndStrikethrough, + emph: emphasisAndStrikethrough, + strike: emphasisAndStrikethrough, + link: markTextHelper_link, + image: markTextHelper_image, + code: markTextHelper_code, + codeBlock: markTextHelper_codeBlock, + blockQuote: blockQuote, + item: markTextHelper_item +}; +var simpleMarkClassNameMap = { + thematicBreak: classNameMap.THEMATIC_BREAK, + table: classNameMap.TABLE, + tableCell: classNameMap.TEXT, + htmlInline: classNameMap.HTML +}; +/** + * Gets mark information to the markdown node. + * @param {Object} node - node returned from ToastMark + * @param {Object} start - start node's data + * @param {Object} end - end node's data + * @param {Object} endLine - end line's data + * @returns {?Object} mark information + * @ignore + */ + +function getMarkInfo(node, start, end, endLine) { + var type = node.type; + + if (isFunction_default()(markNodeFuncMap[type])) { + return markNodeFuncMap[type](node, start, end, endLine); + } + + if (simpleMarkClassNameMap[type]) { + return { + marks: [markTextHelper_markInfo(start, end, simpleMarkClassNameMap[type])] + }; + } + + return null; +} +// CONCATENATED MODULE: ./src/js/markdownEditor.js +function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } it = o[Symbol.iterator](); return it.next.bind(it); } + +function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } + +function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +function markdownEditor_extends() { markdownEditor_extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return markdownEditor_extends.apply(this, arguments); } + +/** + * @fileoverview Implements markdown editor + * @author NHN FE Development Lab + */ + + + + + + + + +var markdownEditor_keyMapper = keyMapper.getSharedInstance(); +var defaultToolbarState = { + strong: false, + emph: false, + strike: false, + thematicBreak: false, + blockQuote: false, + code: false, + codeBlock: false, + list: false, + taskList: false, + orderedList: false, + heading: false, + table: false +}; + +function getToolbarStateType(_ref) { + var type = _ref.type, + listData = _ref.listData; + + if (type === 'list' || type === 'item') { + if (listData.task) { + return 'taskList'; + } + + return listData.type === 'ordered' ? 'orderedList' : 'list'; + } + + if (type.indexOf('table') !== -1) { + return 'table'; + } + + return type; +} + +function getToolbarState(targetNode, ch, mdLine, mdCh) { + var state = markdownEditor_extends({}, defaultToolbarState); + + var listEnabled = false; + Object(markdown["n" /* traverseParentNodes */])(targetNode, function (mdNode) { + var type = getToolbarStateType(mdNode); + + if (!isBoolean_default()(state[type])) { + return; + } + + if (type === 'list' || type === 'orderedList') { + if (!listEnabled) { + state[type] = true; + listEnabled = true; + } + } else { + state[type] = true; + } + }); // if position is matched to start, end position of inline node, highlighting is ignored + + if (Object(markdown["k" /* isStyledTextNode */])(targetNode) && (mdCh === ch && Object(markdown["d" /* getMdEndLine */])(targetNode) === mdLine || mdCh === Object(markdown["c" /* getMdEndCh */])(targetNode) + 1 && mdLine === Object(markdown["d" /* getMdEndLine */])(targetNode) || mdCh === Object(markdown["e" /* getMdStartCh */])(targetNode) && mdLine === Object(markdown["f" /* getMdStartLine */])(targetNode))) { + state[targetNode.type] = false; + } + + return state; +} +/** + * Return whether state changed or not + * @param {object} previousState - Previous state + * @param {object} currentState - Current state + * @returns {boolean} - changed state + * @private + */ + + +function isToolbarStateChanged(previousState, currentState) { + if (!previousState && !currentState) { + return false; + } + + if (!previousState && currentState || previousState && !currentState) { + return true; + } + + return Object.keys(currentState).some(function (type) { + return previousState[type] !== currentState[type]; + }); +} + +var ATTR_NAME_MARK = 'data-tui-mark'; +var TASK_MARKER_KEY_RX = /x|backspace/i; +/** + * Class MarkdownEditor + * @param {HTMLElement} el - container element + * @param {EventManager} eventManager - event manager + * @param {Object} options - options of editor + */ + +var markdownEditor_MarkdownEditor = /*#__PURE__*/function (_CodeMirrorExt) { + _inheritsLoose(MarkdownEditor, _CodeMirrorExt); + + function MarkdownEditor(el, eventManager, toastMark, options) { + var _this; + + _this = _CodeMirrorExt.call(this, el, { + dragDrop: true, + allowDropFileTypes: ['image'], + extraKeys: { + Enter: function Enter() { + return _this.eventManager.emit('command', 'AddLine'); + }, + Tab: function Tab() { + return _this.eventManager.emit('command', 'MoveNextCursorOrIndent'); + }, + 'Shift-Tab': function ShiftTab() { + return _this.eventManager.emit('command', 'MovePrevCursorOrOutdent'); + }, + 'Shift-Ctrl-X': function ShiftCtrlX() { + return _this.eventManager.emit('command', 'ToggleTaskMarker'); + } + }, + viewportMargin: options && options.height === 'auto' ? Infinity : 10 + }) || this; + _this.eventManager = eventManager; + _this.componentManager = new componentManager(_assertThisInitialized(_this)); + _this.toastMark = toastMark; + + _this.componentManager.addManager(mdListManager); + /** + * latest state info + * @type {object} + * @private + */ + + + _this._latestState = null; + /** + * map of marked lines + * @type {Object. + */ + + + + + + + +var DEFAULT_COLOR = 'rgb(34, 34, 34)'; +/** + * Class WwPasteContentHelper + * @param {WysiwygEditor} wwe - wysiwygEditor instance + * @ignore + */ + +var wwPasteContentHelper_WwPasteContentHelper = /*#__PURE__*/function () { + function WwPasteContentHelper(wwe) { + this.wwe = wwe; + } + /** + * Process paste data before paste + * @param {HTMLElement} container - clipboard container + */ + + + var _proto = WwPasteContentHelper.prototype; + + _proto.preparePaste = function preparePaste(container) { + var range = this.wwe.getEditor().getSelection().cloneRange(); + var wwCodeblockManager = this.wwe.componentManager.getManager('codeblock'); + var firstBlockIsTaken = false; + var tempContainer = document.createElement('div'); + var nodeName, node, isPastingList; + + this._pasteFirstAid(container); + + var childNodes = toArray_default()(container.childNodes); + + while (childNodes.length) { + node = childNodes[0]; + nodeName = dom["a" /* default */].getNodeName(node); + isPastingList = nodeName === 'LI' || nodeName === 'UL' || nodeName === 'OL'; + + if (wwCodeblockManager.isInCodeBlock(range)) { + dom["a" /* default */].append(tempContainer, wwCodeblockManager.prepareToPasteOnCodeblock(childNodes)); + } else if (isPastingList) { + dom["a" /* default */].append(tempContainer, this._prepareToPasteList(childNodes, range, firstBlockIsTaken)); + firstBlockIsTaken = true; + } else { + dom["a" /* default */].append(tempContainer, childNodes.shift()); + } + } + + container.innerHTML = tempContainer.innerHTML; + } + /** + * Wrap orphan node(inline, text) with div element + * @param {HTMLElement} container - clipboard container + * @returns {DocumentFragment} + * @private + */ + ; + + _proto._wrapOrphanNodeWithDiv = function _wrapOrphanNodeWithDiv(container) { + var tempContainer = document.createElement('div'); + var currentDiv; + toArray_default()(container.childNodes).forEach(function (node) { + var isTextNode = node.nodeType === 3; + /* eslint-disable max-len */ + + var isInlineNode = /^(SPAN|A|CODE|EM|I|STRONG|B|S|U|ABBR|ACRONYM|CITE|DFN|KBD|SAMP|VAR|BDO|Q|SUB|SUP)$/gi.test(node.tagName); + var isBR = node.nodeName === 'BR'; + /* eslint-enable max-len */ + + if (isTextNode || isInlineNode || isBR) { + if (!currentDiv) { + currentDiv = document.createElement('div'); + tempContainer.appendChild(currentDiv); + } + + currentDiv.appendChild(node); + + if (isBR) { + currentDiv = null; + } + } else { + if (currentDiv && currentDiv.lastChild.tagName !== 'BR') { + currentDiv.appendChild(document.createElement('br')); + } + + currentDiv = null; + tempContainer.appendChild(node); + } + }); + return tempContainer.innerHTML; + } + /** + * Sanitize content of element + * @param {HTMLElement} container - root element of content to sanitize + * @private + */ + ; + + _proto._sanitizeHtml = function _sanitizeHtml(container) { + var sanitizer = this.wwe.getSanitizer(); + var html = Object(htmlSanitizer["a" /* default */])(container.innerHTML, true); + + if (sanitizer && sanitizer !== htmlSanitizer["a" /* default */]) { + html = sanitizer(html); + } + + container.innerHTML = html; + } + /** + * Processing paste data after paste + * @param {HTMLElement} container - clipboard container + * @private + */ + ; + + _proto._pasteFirstAid = function _pasteFirstAid(container) { + var _this = this; + + this._sanitizeHtml(container); + + dom["a" /* default */].findAll(container, '*').forEach(function (node) { + _this._removeStyles(node); + }); + var blockTags = 'div, section, article, aside, nav, menus, p'; + + this._unwrapIfNonBlockElementHasBr(container); + + this._unwrapNestedBlocks(container, blockTags); + + this._removeUnnecessaryBlocks(container, blockTags); + + container.innerHTML = this._wrapOrphanNodeWithDiv(container); + + this._preprocessPreElement(container); + + this._preprocessListElement(container); + + this._preprocessTableElement(container); + + toArray_default()(container.children).forEach(function (childNode) { + if (dom["a" /* default */].getNodeName(childNode) === 'BR') { + dom["a" /* default */].remove(childNode); + } + }); + }; + + _proto._preprocessListElement = function _preprocessListElement(container) { + var wwListManager = this.wwe.componentManager.getManager('list'); + container.innerHTML = wwListManager.convertToArbitraryNestingList(container.innerHTML); + } + /** + * PRE tag formatting + * @param {HTMLElement} container - clipboard container + * @private + */ + ; + + _proto._preprocessPreElement = function _preprocessPreElement(container) { + var wwCodeblockManager = this.wwe.componentManager.getManager('codeblock'); + wwCodeblockManager.modifyCodeBlockForWysiwyg(container); + } + /** + * Unwrap span children of document fragment with div element + * @param {HTMLElement} container - clipboard container + * @private + */ + ; + + _proto._unwrapIfNonBlockElementHasBr = function _unwrapIfNonBlockElementHasBr(container) { + var nonBlockElements = dom["a" /* default */].findAll(container, 'span, a, b, em, i, s'); + nonBlockElements.forEach(function (node) { + var brChildren = dom["a" /* default */].children(node, 'br'); + + if (brChildren.length && node.nodeName !== 'LI' && node.nodeName !== 'UL') { + dom["a" /* default */].unwrap(node); + } + }); + } + /** + * Unwrap nested block elements + * @param {HTMLElement} container - clipboard container + * @param {string} blockTags - Tag names of block tag + * @private + */ + ; + + _proto._unwrapNestedBlocks = function _unwrapNestedBlocks(container, blockTags) { + var leafElements = dom["a" /* default */].findAll(container, '*').filter(function (node) { + return !matches_default()(node, 'b,s,i,em,code,span,hr') && !node.firstChild; + }); + leafElements.forEach(function (node) { + var leafElement = node.nodeName === 'BR' ? node.parentNode : node; + + while (dom["a" /* default */].parents(leafElement, blockTags).length) { + var parent = dom["a" /* default */].parent(leafElement, blockTags); + + if (parent && parent !== container) { + dom["a" /* default */].unwrap(parent); + } else { + leafElement = leafElement.parentElement; + } + } + }); + } + /** + * Remove unnecessary block element in pasting data + * @param {HTMLElement} container - clipboard container + * @param {string} blockTags - Tag names of block tag + * @private + */ + ; + + _proto._removeUnnecessaryBlocks = function _removeUnnecessaryBlocks(container, blockTags) { + dom["a" /* default */].findAll(container, blockTags).forEach(function (blockElement) { + var tagName = blockElement.tagName; + var isDivElement = tagName === 'DIV'; + var isInListItem = !!dom["a" /* default */].parent(blockElement, 'li'); + var isInBlockquote = !!dom["a" /* default */].parent(blockElement, 'blockquote'); + var hasBlockChildElement = !!dom["a" /* default */].children(blockElement, blockTags).length; + + if (isDivElement && (isInListItem || isInBlockquote || !hasBlockChildElement)) { + return; + } + + if (blockElement.lastChild && blockElement.lastChild.nodeName !== 'BR') { + blockElement.appendChild(document.createElement('br')); + } + + dom["a" /* default */].replaceWith(blockElement, blockElement.innerHTML); + }); + } + /** + * Remove inline style + * @param {Node} node Node for remove style attribute + * @private + */ + ; + + _proto._removeStyles = function _removeStyles(node) { + var colorValue; + + if (dom["a" /* default */].getNodeName(node) !== 'SPAN') { + node.removeAttribute('style'); + } else { + // Most browser return computed color value even if without style attribute + if (node.getAttribute('style')) { + colorValue = node.style.color; + } + + node.removeAttribute('style'); + + if (colorValue && colorValue !== DEFAULT_COLOR) { + css_default()(node, { + color: colorValue + }); + } else { + dom["a" /* default */].unwrap(node); + } + } + } + /** + * Processing before paste list + * @param {Array.} nodes Pasting data + * @param {object} rangeInfo Range information + * @param {boolean} firstBlockIsTaken Whether first block element taken or not + * @returns {DocumentFragment} + * @private + */ + ; + + _proto._prepareToPasteList = function _prepareToPasteList(nodes, rangeInfo, firstBlockIsTaken) { + var nodeName = dom["a" /* default */].getNodeName(nodes[0]); + var node = nodes.shift(); + var newFragment = this.wwe.getEditor().getDocument().createDocumentFragment(); // IE somethimes returns ul without li + + if (nodeName !== 'LI' && nodes.length && nodes[0].tagName === 'LI') { + nodeName = 'LI'; + node = this._makeNodeAndAppend({ + tagName: nodeName + }, node); + } // pasting list into list, we should care indentation + + + if (nodeName === 'OL' || nodeName === 'UL') { + // ignore cursor if pasting data has block + if (!firstBlockIsTaken && this.wwe.getEditor().hasFormat('LI')) { + dom["a" /* default */].append(newFragment, this._wrapCurrentFormat(node)); + } else { + newFragment.appendChild(node); + } + } else if (nodeName === 'LI') { + // handle list group + var listGroup = this.wwe.getEditor().getDocument().createDocumentFragment(); + listGroup.appendChild(node); + + while (nodes.length && nodes[0].tagName === 'LI') { + listGroup.appendChild(nodes.shift()); + } // pasting list into list, we should care indentation + // ignore cursor if pasting data has block + + + if (!firstBlockIsTaken && this.wwe.getEditor().hasFormat('LI')) { + dom["a" /* default */].append(newFragment, this._wrapCurrentFormat(listGroup)); + } else if (rangeInfo && (rangeInfo.commonAncestorName === 'UL' || rangeInfo.commonAncestorName === 'OL')) { + dom["a" /* default */].append(newFragment, this._makeNodeAndAppend({ + tagName: rangeInfo.commonAncestorName + }, listGroup)); // list from outside + } else { + dom["a" /* default */].append(newFragment, this._makeNodeAndAppend({ + tagName: 'UL' + }, listGroup)); + } + } + + return this._getResolvePastedListDepthToCurrentDepth(rangeInfo.startContainer, node, newFragment); + } + /** + * Unwrap fragment first child for pasting node inline + * @param {Node} node Pasting DocumentFragment + * @returns {NodeList} + * @private + */ + ; + + _proto._unwrapFragmentFirstChildForPasteAsInline = function _unwrapFragmentFirstChildForPasteAsInline(node) { + dom["a" /* default */].findAll(node, 'br').forEach(function (br) { + return dom["a" /* default */].remove(br); + }); + return node.childNodes; + } + /** + * Wrap nodes with current format + * @param {DocumentFragment} nodes P + * @returns {HTMLElement} + * @private + */ + ; + + _proto._wrapCurrentFormat = function _wrapCurrentFormat(nodes) { + var _this2 = this; + + var currentTagName; // expand to pasting area + + this._eachCurrentPath(function (path) { + if (path.tagName !== 'DIV') { + if (dom["a" /* default */].isElemNode(nodes)) { + currentTagName = nodes.tagName; + } else { + currentTagName = nodes.firstChild.tagName; + } + + if (path.tagName !== currentTagName) { + nodes = _this2._makeNodeAndAppend(path, nodes); + } + } + }); + + return nodes; + }; + + _proto._eachCurrentPath = function _eachCurrentPath(iteratee) { + var paths = dom["a" /* default */].getPath(this.wwe.getEditor().getSelection().startContainer, this.wwe.getBody()); + + for (var i = paths.length - 1; i > -1; i -= 1) { + iteratee(paths[i]); + } + } + /** _makeNodeAndAppend + * make node and append their own children + * @param {HTMLElement} pathInfo HTMLElement to make + * @param {HTMLElement} content Nodes to append + * @returns {HTMLElement} node + * @private + */ + ; + + _proto._makeNodeAndAppend = function _makeNodeAndAppend(pathInfo, content) { + var node = document.createElement("" + pathInfo.tagName); + node.appendChild(content); + + if (pathInfo.id) { + node.setAttribute('id', pathInfo.id); + } + + if (pathInfo.className) { + addClass_default()(node, pathInfo.className); + } + + return node; + } + /** + * Pasting table element pre-process + * @param {HTMLElement} container - clipboard container + * @private + */ + ; + + _proto._preprocessTableElement = function _preprocessTableElement(container) { + this._removeColgroup(container); + + this._completeTableIfNeed(container); + + this._updateTableIDClassName(container); + } + /** + * Remove colgroup tag + * @param {HTMLElement} container - clipboard container + * @private + **/ + ; + + _proto._removeColgroup = function _removeColgroup(container) { + var colgroup = container.querySelector('colgroup'); + + if (colgroup) { + dom["a" /* default */].remove(colgroup); + } + } + /** + * Complete and append table to fragment + * @param {HTMLElement} container - clipboard container + * @private + */ + ; + + _proto._completeTableIfNeed = function _completeTableIfNeed(container) { + var tableManager = this.wwe.componentManager.getManager('table'); + var wrapperTr = tableManager.wrapDanglingTableCellsIntoTrIfNeed(container); + + if (wrapperTr) { + dom["a" /* default */].append(container, wrapperTr); + } + + var wrapperTbody = tableManager.wrapTrsIntoTbodyIfNeed(container); + + if (wrapperTbody) { + dom["a" /* default */].append(container, wrapperTbody); + } + + var wrapperTable = tableManager.wrapTheadAndTbodyIntoTableIfNeed(container); + + if (wrapperTable) { + dom["a" /* default */].append(container, wrapperTable); + } + } + /** + * Update table ID class name in fragment + * @param {HTMLElement} container - clipboard container + * @private + */ + ; + + _proto._updateTableIDClassName = function _updateTableIDClassName(container) { + var tableManager = this.wwe.componentManager.getManager('table'); + var tables = dom["a" /* default */].findAll(container, 'table'); + tables.forEach(function (table) { + var foundClassName = table.className.match(/.*\s*(te-content-table-\d+)\s*.*/); + + if (foundClassName) { + removeClass_default()(table, foundClassName[0]); + } + }); + tables.forEach(function (table) { + addClass_default()(table, tableManager.getTableIDClassName()); + }); + } + /** + * get the list resolved the depth to current list depth + * @param {HTMLElement} currentEl - current list element + * @param {HTMLElement} orgPastedNode - original pasted data + * @param {DocumentFragment} fragment - preprocessed data + * @returns {HTMLElement} resolved element + * @private + */ + ; + + _proto._getResolvePastedListDepthToCurrentDepth = function _getResolvePastedListDepthToCurrentDepth(currentEl, orgPastedNode, fragment) { + var currentListDepth = this._getListDepth(currentEl); + + var continuousDepth = this._getContinuousDepth(orgPastedNode); + + fragment = this._getRemovedUnnecessaryListWrapper(fragment, orgPastedNode); // If the depth of the pasted data is greater than current depth, get child element for resolving the depth. + // For example, If 2-depth list is pasted to 1-depth list element, 2-depth list should be changed to 1-depth. + + while (currentListDepth < continuousDepth) { + if (fragment.firstChild.tagName !== 'UL' && fragment.firstChild.tagName !== 'OL') { + break; + } + + var childNodes = toArray_default()(fragment.childNodes); + fragment = fragment.firstChild; + /* eslint-disable no-loop-func */ + + childNodes.filter(function (node) { + return node !== fragment; + }).forEach(function (node) { + fragment.insertAdjacentElement('beforeend', node); + }); + /* eslint-enable no-loop-func */ + + continuousDepth -= 1; + } // If the depth of the pasted data is less than current depth, wrap the list element for resolving the depth. + // For example, If 1-depth list is pasted to 2-depth list element, 1-depth list should be changed to 2-depth. + + + while (currentListDepth && currentListDepth > continuousDepth) { + var rootList = fragment.firstChild.parentElement; + var list = document.createElement(rootList.tagName); + list.appendChild(rootList); + fragment = list; + continuousDepth += 1; + } + + if (currentListDepth && !currentEl.textContent) { + dom["a" /* default */].remove(currentEl); + } + + return fragment; + } + /** + * get the depth of the list item element + * @param {HTMLElement} el - target element + * @returns {number} depth + * @private + */ + ; + + _proto._getListDepth = function _getListDepth(el) { + var depth = 0; // Since the list outside the editor can be found, + // so make sure to traverse only the editor's container. + + var root = this.wwe.getBody(); + + while (el && el !== root) { + if (el.tagName === 'UL' || el.tagName === 'OL') { + depth += 1; + } + + el = el.parentNode; + } + + return depth; + } + /** + * get the continuous depth of the list. + * the continuous depth of below example is 2 + *
    + *
  • + *
      + *
    • ...
    • + *
        ...
      + *
    + *
  • + *
+ * + * @param {HTMLElement} el - target element + * @returns {number} depth + * @private + */ + ; + + _proto._getContinuousDepth = function _getContinuousDepth(el) { + var depth = 0; + + while (el && (el.tagName === 'UL' || el.tagName === 'OL')) { + depth += 1; + + if (el.childNodes.length > 1) { + break; + } + + el = el.firstChild; + } + + return depth; + } + /** + * get the element which is removed unnecessay list wrapper element + * @param {HTMLElement} el - target element + * @param {HTMLElement} orgEl - target element + * @returns {HTMLElement} el + * @private + */ + ; + + _proto._getRemovedUnnecessaryListWrapper = function _getRemovedUnnecessaryListWrapper(el, orgEl) { + while (el.querySelectorAll('ul,ol').length > orgEl.querySelectorAll('ul,ol').length) { + el = el.firstChild; + } + + return el; + }; + + return WwPasteContentHelper; +}(); + +/* harmony default export */ var wwPasteContentHelper = (wwPasteContentHelper_WwPasteContentHelper); +// CONCATENATED MODULE: ./src/js/wwTablePasteHelper.js +/** + * @fileoverview Paste helper when past to table + * @author NHN FE Development Lab + */ + + + + +/** + * Class WwTablePasteHelper + * @param {WysiwygEditor} wwe - WysiwygEditor instance + * @ignore + */ + +var wwTablePasteHelper_WwTablePasteHelper = /*#__PURE__*/function () { + function WwTablePasteHelper(wwe) { + this.wwe = wwe; + } + /** + * Prossse paste clipboardEvent + * @param {ClipboardEvent} ev - ClipboardEvent + */ + + + var _proto = WwTablePasteHelper.prototype; + + _proto.pasteClipboard = function pasteClipboard(ev) { + var cbData = ev.clipboardData || window.clipboardData; + var items = cbData && cbData.items; + + if (items) { + this._pasteClipboardItem(items); + + ev.preventDefault(); + } else { + this._pasteClipboardUsingPasteArea(); + + ev.squirePrevented = true; + } + } + /** + * ClipboardEvent is not supported in IE. + * To get clipboard, create temporay element and then paste into that element. + * After end of paste, can get clipboard from that temporary element. + * @param {ClipboardEvent} ev - ClipboardEvent + * @private + */ + ; + + _proto._pasteClipboardUsingPasteArea = function _pasteClipboardUsingPasteArea() { + var _this = this; + + var sq = this.wwe.getEditor(); + var range = sq.getSelection(); + var startContainer = range.startContainer, + startOffset = range.startOffset, + endContainer = range.endContainer, + endOffset = range.endOffset; + var pasteArea = document.createElement('div'); + var _document = document, + body = _document.body; + pasteArea.setAttribute('contenteditable', true); + pasteArea.setAttribute('style', 'position:fixed; overflow:hidden; top:0; right:100%; width:1px; height:1px;'); + body.appendChild(pasteArea); + range.selectNodeContents(pasteArea); + sq.setSelection(range); + setTimeout(function () { + var clipboard = body.removeChild(pasteArea); + range.setStart(startContainer, startOffset); + range.setEnd(endContainer, endOffset); + sq.focus(); + sq.setSelection(range); + + _this._pasteClipboardHtml(clipboard.innerHTML); + }); + } + /** + * Paste items of clipboard data + * @param {DataTransfer.items} items - items of clipboarddata + * @private + */ + ; + + _proto._pasteClipboardItem = function _pasteClipboardItem(items) { + var _this2 = this; + + var textItem = null; + var htmlItem = null; + toArray_default()(items).forEach(function (item) { + if (item.type === 'text/html') { + htmlItem = item; + } else if (item.type === 'text/plain') { + textItem = item; + } + }); + + if (htmlItem) { + htmlItem.getAsString(function (html) { + _this2._pasteClipboardHtml(html); + }); + } else if (textItem) { + textItem.getAsString(function (text) { + var fragment = dom["a" /* default */].getFragmentReplacedByNewlineToBr(text); + + _this2._pasteClipboardContainer(fragment); + }); + } + } + /** + * Get sanitized html as dom fragment + * @param {string} html - html string to sanitize + * @returns {DocumentFragment} sanitized html + * @private + */ + ; + + _proto._getSanitizedHtml = function _getSanitizedHtml(html) { + var sanitizer = this.wwe.getSanitizer(); + html = Object(htmlSanitizer["a" /* default */])(html, true); + + if (sanitizer && sanitizer !== htmlSanitizer["a" /* default */]) { + html = sanitizer(html); + } + + var container = document.createElement('div'); + container.innerHTML = html; + return dom["a" /* default */].finalizeHtml(container); + }; + + _proto._convertToMsoList = function _convertToMsoList(html) { + var container = document.createElement('div'); + container.innerHTML = html; + convertMsoParagraphsToList(container); + return container.innerHTML; + } + /** + * Paste html of clipboard + * @param {string} html - html + * @private + */ + ; + + _proto._pasteClipboardHtml = function _pasteClipboardHtml(html) { + var container = document.createDocumentFragment(); + var startFramgmentStr = ''; + var endFragmentStr = ''; + var startFragmentIndex = html.indexOf(startFramgmentStr); + var endFragmentIndex = html.lastIndexOf(endFragmentStr); + + if (startFragmentIndex > -1 && endFragmentIndex > -1) { + html = html.slice(startFragmentIndex + startFramgmentStr.length, endFragmentIndex); + } // Wrap with if html contains dangling tags + // Dangling tag is that tag does not have as parent node. + + + if (/<\/td>((?!<\/tr>)[\s\S])*$/i.test(html)) { + html = "" + html + ""; + } // Wrap with if html contains dangling tags + // Dangling tag is that tag does not have
as parent node. + + + if (/<\/tr>((?!<\/table>)[\s\S])*$/i.test(html)) { + html = "
" + html + "
"; + } + + if (isFromMso(html)) { + html = this._convertToMsoList(html); + } + + container.appendChild(this._getSanitizedHtml(html)); + + this._pasteClipboardContainer(container); + } + /** + * Paste container of clipboard + * @param {DocumentFragment} clipboardContainer - clipboard + * @private + */ + ; + + _proto._pasteClipboardContainer = function _pasteClipboardContainer(clipboardContainer) { + var sq = this.wwe.getEditor(); + var childNodes = clipboardContainer.childNodes; + var containsOneTableOnly = childNodes.length === 1 && childNodes[0].nodeName === 'TABLE'; + + if (containsOneTableOnly) { + var tableManager = this.wwe.componentManager.getManager('table'); + tableManager.pasteTableData(clipboardContainer); + } else { + var range = sq.getSelection().cloneRange(); + + var fragment = this._preparePasteDocumentFragment(clipboardContainer); + + sq.saveUndoState(range); + + if (!range.collapsed) { + this._deleteContentsRange(range); + } + + if (dom["a" /* default */].isTextNode(range.startContainer)) { + this._pasteIntoTextNode(range, fragment); + } else { + this._pasteIntoElements(range, fragment); + } + + sq.setSelection(range); + } + } + /** + * Prepare clipboard for paste to table + * @param {DocumentFragment} clipboardContainer - clipboard + * @returns {DocumentFragment} processed result + * @private + */ + ; + + _proto._preparePasteDocumentFragment = function _preparePasteDocumentFragment(clipboardContainer) { + var childNodes = clipboardContainer.childNodes; + var fragment = document.createDocumentFragment(); + + if (childNodes.length) { + fragment.appendChild(this._unwrapBlock(clipboardContainer)); + } else if (this._isPossibleInsertToTable(clipboardContainer)) { + fragment.appendChild(clipboardContainer); + } + + return fragment; + } + /** + * unwrap block node + * @param {Node} node - target node + * @returns {DocumentFragment} processed result + * @private + */ + ; + + _proto._unwrapBlock = function _unwrapBlock(node) { + var fragment = document.createDocumentFragment(); + var childNodes = toArray_default()(node.childNodes); + + while (childNodes.length) { + var child = childNodes.shift(); + + if (this._isPossibleInsertToTable(child)) { + fragment.appendChild(child); + } else { + fragment.appendChild(this._unwrapBlock(child)); // If current child is last or fragment already has last br, + // appending br would create unintended line break. + + var lastChild = fragment.lastChild; + + if (childNodes.length && lastChild && lastChild.nodeName !== 'BR') { + fragment.appendChild(document.createElement('br')); + } + } + } + + return fragment; + }; + + _proto._isPossibleInsertToTable = function _isPossibleInsertToTable(node) { + var nodeName = node.nodeName; + var isChildlessCode = nodeName === 'CODE' && node.childNodes.length > 1; + var isList = nodeName === 'UL' || nodeName === 'OL'; + return !isChildlessCode && (isList || dom["a" /* default */].isMDSupportInlineNode(node) || dom["a" /* default */].isTextNode(node)); + } + /** + * paste fragment to offset of range.startContainer + * @param {Range} range - selection range + * @param {DocumentFragment} fragment - paste data + * @private + */ + ; + + _proto._pasteIntoElements = function _pasteIntoElements(range, fragment) { + var container = range.startContainer, + offset = range.startOffset; + var node = dom["a" /* default */].getChildNodeByOffset(container, offset); + + if (!node) { + // For example when container is br, br don't have child, so node is null + if (container.nodeName === 'TD') { + container.appendChild(fragment); + range.setStart(container, container.childNodes.length); + } else { + var parentNode = container.parentNode, + nextSibling = container.nextSibling; + parentNode.insertBefore(fragment, nextSibling); + + if (nextSibling) { + range.setStart(nextSibling, 0); + } else { + range.setStartAfter(parentNode.lastChild); + } + } + } else { + container.insertBefore(fragment, node); + range.setStart(node, 0); + } + + range.collapse(true); + } + /** + * paste fragment to offset of text node + * @param {Range} range - selection range + * @param {DocumentFragment} fragment - paste data + * @private + */ + ; + + _proto._pasteIntoTextNode = function _pasteIntoTextNode(range, fragment) { + var container = range.startContainer, + offset = range.startOffset; + var parentNode = container.parentNode, + textContent = container.textContent; + var prevText = textContent.slice(0, offset); + var postText = textContent.slice(offset, textContent.length); + var fragmentChildNodes = fragment.childNodes; + var firstChild = fragmentChildNodes[0]; + var isFragmenthasOneTextNode = fragmentChildNodes.length === 1 && dom["a" /* default */].isTextNode(firstChild); + + if (!prevText) { + parentNode.insertBefore(fragment, container); + range.setStart(container, 0); + } else if (!postText) { + var nextSibling = container.nextSibling; + parentNode.insertBefore(fragment, nextSibling); + range.setStartAfter(nextSibling); + } else if (isFragmenthasOneTextNode) { + var firstChildText = firstChild.textContent; + container.textContent = "" + prevText + firstChildText + postText; + range.setStart(container, prevText.length + firstChildText.length); + } else { + var resultFragment = document.createDocumentFragment(); + resultFragment.appendChild(document.createTextNode(prevText)); + resultFragment.appendChild(fragment); + resultFragment.appendChild(document.createTextNode(postText)); + parentNode.replaceChild(resultFragment, container); + var childNodesArray = toArray_default()(parentNode.childNodes); + var index = 0; + childNodesArray.forEach(function (child, i) { + if (child.textContent === postText) { + index = i; + } + }); + range.setStart(parentNode.childNodes[index], 0); + } + + range.collapse(true); + } + /** + * delete contents of range that is not collapse + * @param {Range} range - range is not collapse + * @private + */ + ; + + _proto._deleteContentsRange = function _deleteContentsRange(range) { + var startContainer = range.startContainer, + startOffset = range.startOffset, + endContainer = range.endContainer, + endOffset = range.endOffset; + + if (startContainer === endContainer) { + this._deleteContentsByOffset(startContainer, startOffset, endOffset); + + range.setStart(startContainer, startOffset); + range.collapse(true); + } else { + this._deleteNotCollapsedRangeContents(range); + } + }; + + _proto._deleteNotCollapsedRangeContents = function _deleteNotCollapsedRangeContents(range) { + var startContainer = range.startContainer, + startOffset = range.startOffset, + endContainer = range.endContainer, + endOffset = range.endOffset; + var common = range.commonAncestorContainer; + + var startBlock = this._getBlock(startContainer, common, startOffset); + + var endBlock = this._getBlock(endContainer, common, endOffset - 1); + + if (startBlock === endBlock) { + this._removeInSameBlock(startBlock, startContainer, endContainer, startOffset, endOffset); // When endContainer is not same endBlock, endBlock is removed. + // For example, aaa| <- this is cursor. + // When cursor is last, endContainer would be 'TD' and endBlock is text node + // In this case, remove all 'aaa' so endBlock should be null. + + + endBlock = endContainer !== endBlock ? null : endBlock; + } else { + var nextOfstartBlock = startBlock.nextSibling; + + if (startContainer.nodeName === 'TD') { + nextOfstartBlock = this._removeOneLine(startBlock); + } else { + // Remove child nodes from node of startOffset in startContainer. + this._deleteContentsByOffset(startContainer, startOffset, dom["a" /* default */].getOffsetLength(startContainer)); // Remove nodes from startContainer in startBlock + + + dom["a" /* default */].removeNodesByDirection(startBlock, startContainer, false); + } + + if (endContainer.nodeName === 'TD') { + endBlock = this._removeOneLine(endBlock); + } else { + // Remove child nodes until node of endOffset in endContainer. + this._deleteContentsByOffset(endContainer, 0, endOffset); // Remove nodes until endContainer in endBlock + + + dom["a" /* default */].removeNodesByDirection(endBlock, endContainer, true); + } // Remove nodes between startBlock and endBlock + + + dom["a" /* default */].removeChildFromStartToEndNode(common, nextOfstartBlock, endBlock); + } + + if (endBlock) { + range.setStart(endBlock, 0); + } else { + range.setStartAfter(startBlock); + } + + range.collapse(true); + }; + + _proto._removeInSameBlock = function _removeInSameBlock(block, startContainer, endContainer, startOffset, endOffset) { + var start = startContainer === block ? startOffset : 0; + var end = endContainer === block ? endOffset : dom["a" /* default */].getOffsetLength(block); + + this._deleteContentsByOffset(block, start, end); + }; + + _proto._removeOneLine = function _removeOneLine(node) { + var nextSibling = node.nextSibling, + parentNode = node.parentNode; + var next = nextSibling; + parentNode.removeChild(node); + + if (nextSibling && nextSibling.nodeName === 'BR') { + next = nextSibling.nextSibling; + parentNode.removeChild(nextSibling); + } + + return next; + } + /** + * Find parent block node of startContainer and endContainer + * If startContainer or endContainer is same commonAncestor, + * find node at offset of startContainer and endContainer. + * @param {Node} node - startContainer or endContainer + * @param {Node} parent - commonAncestor + * @param {Number} offset - startOffset or endOffset-1 + * @returns {Node} block node + * @private + */ + ; + + _proto._getBlock = function _getBlock(node, parent, offset) { + return dom["a" /* default */].getParentUntil(node, parent) || dom["a" /* default */].getChildNodeByOffset(node, offset); + } + /** + * delete contents from start offset to end offset + * @param {Node} container - container + * @param {Number} startOffset - start offset + * @param {Number} endOffset - end offset + * @private + */ + ; + + _proto._deleteContentsByOffset = function _deleteContentsByOffset(container, startOffset, endOffset) { + if (dom["a" /* default */].isTextNode(container)) { + var textContent = container.textContent; + var prevText = textContent.slice(0, startOffset); + var postText = textContent.slice(endOffset, textContent.length); + container.textContent = "" + prevText + postText; + } else { + var startNode = dom["a" /* default */].getChildNodeByOffset(container, startOffset); + var endNode = dom["a" /* default */].getChildNodeByOffset(container, endOffset); + + if (startNode) { + dom["a" /* default */].removeChildFromStartToEndNode(container, startNode, endNode || null); + } + } + }; + + return WwTablePasteHelper; +}(); + +/* harmony default export */ var wwTablePasteHelper = (wwTablePasteHelper_WwTablePasteHelper); +// CONCATENATED MODULE: ./src/js/wwClipboardManager.js +/** + * @fileoverview Implements wysiwyg editor clipboard manager + * @author NHN FE Development Lab + */ + + + + + + + + + +var PASTE_TABLE_BOOKMARK = 'tui-paste-table-bookmark'; +var PASTE_TABLE_CELL_BOOKMARK = 'tui-paste-table-cell-bookmark'; +/** + * Class WwClipboardManager + * @param {WysiwygEditor} wwe - WysiwygEditor instance + * @ignore + */ + +var wwClipboardManager_WwClipboardManager = /*#__PURE__*/function () { + function WwClipboardManager(wwe) { + this.wwe = wwe; + this._pch = new wwPasteContentHelper(this.wwe); + this._tablePasteHelper = new wwTablePasteHelper(this.wwe); + this._selectedSellCount = 0; + this._clipboardArea = null; + } + /** + * initialize + */ + + + var _proto = WwClipboardManager.prototype; + + _proto.init = function init() { + var _this = this; + + this.wwe.eventManager.listen('willPaste', function (ev) { + return _this._executeHandler(_this._onWillPaste.bind(_this), ev); + }); + this.wwe.eventManager.listen('copy', function (ev) { + return _this._executeHandler(_this._onCopyCut.bind(_this), ev); + }); + this.wwe.eventManager.listen('copyAfter', function (ev) { + return _this._executeHandler(_this._onCopyAfter.bind(_this), ev); + }); + this.wwe.eventManager.listen('cut', function (ev) { + return _this._executeHandler(_this._onCopyCut.bind(_this), ev); + }); + this.wwe.eventManager.listen('cutAfter', function (ev) { + return _this._executeHandler(_this._onCutAfter.bind(_this), ev); + }); + this.wwe.eventManager.listen('paste', function (ev) { + return _this._executeHandler(_this._onPasteIntoTable.bind(_this), ev); + }); + }; + + _proto._executeHandler = function _executeHandler(handler, event) { + if (event.source === 'wysiwyg') { + handler(event); + } + }; + + _proto._onCopyCut = function _onCopyCut(event) { + var tableManager = this.wwe.componentManager.getManager('tableSelection'); + var selectedCellCount = tableManager.getSelectedCells().length; + + if (!selectedCellCount) { + // preserve selection range in a cell, let squire do the job + return; + } + + if (!tableManager.mergedTableSelectionManager) { + // set selection range to all contents in selected cells, then squire + tableManager.createRangeBySelectedCells(); + return; + } + + var editor = this.wwe.getEditor(); + var clipboardEvent = event.data; + var range = editor.getSelection().cloneRange(); + var clipboardContainer = document.createElement('div'); + + this._extendRange(range); + + clipboardContainer.innerHTML = range.cloneContents(); + + this._updateCopyDataForListTypeIfNeed(range, clipboardContainer); + + this.wwe.eventManager.emit('copyBefore', { + source: 'wysiwyg', + clipboardContainer: clipboardContainer + }); + + this._setClipboardData(clipboardEvent, clipboardContainer.innerHTML, clipboardContainer.textContent); + }; + + _proto._clearClipboardArea = function _clearClipboardArea() { + if (this._clipboardArea) { + dom["a" /* default */].remove(this._clipboardArea); + this._clipboardArea = null; + } + }; + + _proto._onCopyAfter = function _onCopyAfter() { + this.wwe.getEditor().getBody().focus(); + + this._clearClipboardArea(); + }; + + _proto._onCutAfter = function _onCutAfter() { + var range = this.wwe.getEditor().getSelection(); + range.deleteContents(); + this.wwe.getEditor().focus(); + + this._clearClipboardArea(); + } + /** + * Process paste event when occured in table + * @param {{source: string, data: event}} event - event + * @private + */ + ; + + _proto._onPasteIntoTable = function _onPasteIntoTable(event) { + var ev = event.data; + var range = this.wwe.getEditor().getSelection(); + + if (this.wwe.isInTable(range) && this._isSingleCellSelected(range)) { + this._tablePasteHelper.pasteClipboard(ev); + } + }; + + _proto._isSingleCellSelected = function _isSingleCellSelected(range) { + var startContainer = range.startContainer, + endContainer = range.endContainer; + return this._getCell(startContainer) === this._getCell(endContainer); + }; + + _proto._getCell = function _getCell(node) { + return node.nodeName === 'TD' ? node : dom["a" /* default */].getParentUntil(node, 'TR'); + }; + + _proto._replaceNewLineToBr = function _replaceNewLineToBr(node) { + var textNodes = dom["a" /* default */].getAllTextNode(node); + textNodes.forEach(function (textNode) { + if (/\n/.test(textNode.nodeValue)) { + textNode.parentNode.innerHTML = textNode.nodeValue.replace(/\n/g, '
'); + } + }); + }; + + _proto._onWillPaste = function _onWillPaste(event) { + var _this2 = this; + + var pasteData = event.data; + var clipboardContainer = document.createElement('div'); + clipboardContainer.appendChild(pasteData.fragment.cloneNode(true)); + + this._preparePaste(clipboardContainer); + + this._setTableBookmark(clipboardContainer); + + pasteData.fragment = document.createDocumentFragment(); + toArray_default()(clipboardContainer.childNodes).forEach(function (element) { + if (dom["a" /* default */].getNodeName(element) === 'DIV') { + _this2._replaceNewLineToBr(element); + } + + pasteData.fragment.appendChild(element); + }); // once right after the squire insertHTML DOM. + + var handler = function handler() { + _this2.wwe.getEditor().removeEventListener('input', handler); + + _this2.wwe.eventManager.emit('wysiwygRangeChangeAfter', _this2); + + _this2._focusTableBookmark(); + }; + + this.wwe.getEditor().addEventListener('input', handler); + }; + + _proto._setClipboardData = function _setClipboardData(clipboardEvent, htmlContent, textContent) { + if (browser_default.a.msie) { + clipboardEvent.squirePrevented = true; + this._clipboardArea = this._createClipboardArea(); + this._clipboardArea.innerHTML = htmlContent; + + this._clipboardArea.focus(); + + window.getSelection().selectAllChildren(this._clipboardArea); + } else { + clipboardEvent.preventDefault(); + clipboardEvent.stopPropagation(); + clipboardEvent.clipboardData.setData('text/html', htmlContent); + clipboardEvent.clipboardData.setData('text/plain', textContent); + } + }; + + _proto._createClipboardArea = function _createClipboardArea() { + var element = document.createElement('div'); + element.setAttribute('contenteditable', true); + css_default()(element, { + position: 'fixed', + overflow: 'hidden', + top: 0, + right: '100%', + width: '1px', + height: '1px' + }); + document.body.appendChild(element); + return element; + } + /** + * Update copy data, when commonAncestorContainer nodeName is list type like UL or OL. + * @param {object} range - text range + * @param {HTMLElement} clipboardContainer - clibpard container element + * @private + */ + ; + + _proto._updateCopyDataForListTypeIfNeed = function _updateCopyDataForListTypeIfNeed(range, clipboardContainer) { + var commonAncestorNodeName = range.commonAncestorContainer.nodeName; + + if (commonAncestorNodeName !== 'UL' && commonAncestorNodeName !== 'OL') { + return; + } + + var newParent = document.createElement(commonAncestorNodeName); + newParent.appendChild(clipboardContainer); + clipboardContainer.innerHTML = ''; + clipboardContainer.appendChild(newParent); + } + /** + * Remove empty font elements. + * @param {HTMLElement} clipboardContainer - cliboard container + * @private + */ + ; + + _proto._removeEmptyFontElement = function _removeEmptyFontElement(clipboardContainer) { + // clipboard data from ms word tend to have unneccesary font tags + var children = dom["a" /* default */].children(clipboardContainer, 'font'); + children.forEach(function (element) { + if (!element.textContent.trim()) { + dom["a" /* default */].remove(element); + } + }); + } + /** + * P tags append 'BR' to make blank line. + * Our viewer renders new line as P tag with margin. + * When pasting text from viewer, insert BR between P tags. + * @param {Node} node - node + * @private + */ + ; + + _proto._preProcessPtag = function _preProcessPtag(node) { + dom["a" /* default */].findAll(node, 'p').forEach(function (pTag) { + if (pTag.lastChild && pTag.lastChild.nodeName !== 'BR') { + pTag.appendChild(document.createElement('br')); + } + + pTag.appendChild(document.createElement('br')); + }); + } + /** + * Prepare paste. + * @param {HTMLElement} clipboardContainer - temporary container for clipboard contents + * @private + */ + ; + + _proto._preparePaste = function _preparePaste(clipboardContainer) { + if (isFromMso(clipboardContainer.innerHTML)) { + convertMsoParagraphsToList(clipboardContainer); + } else { + // When pasting text, the empty line processing differ our viewer and MS Office. + // In our viewer case,

aaa

bbb

have empty line becuase P tags have margin. + // In MS Office case,

aaa

bbb

do not have empty line becuase P tags means just one line. + this._preProcessPtag(clipboardContainer); + } + + this._removeEmptyFontElement(clipboardContainer); + + this._pch.preparePaste(clipboardContainer); + + this.wwe.eventManager.emit('pasteBefore', { + source: 'wysiwyg', + clipboardContainer: clipboardContainer + }); + } + /** + * set table bookmark which will gain focus after document modification ends. + * @param {HTMLElement} clipboardContainer - clipboard container + * @private + */ + ; + + _proto._setTableBookmark = function _setTableBookmark(clipboardContainer) { + var lastNode = clipboardContainer.lastChild; + var isLastNodeTable = lastNode && lastNode.nodeName === 'TABLE'; + + if (isLastNodeTable) { + addClass_default()(lastNode, PASTE_TABLE_BOOKMARK); + } + } + /** + * Focus to table after document modification. + * @param {object} sq - squire editor instance + * @private + */ + ; + + _proto._focusTableBookmark = function _focusTableBookmark() { + var sq = this.wwe.getEditor(); + var range = sq.getSelection().cloneRange(); + var bookmarkedTable = sq.getBody().querySelector("." + PASTE_TABLE_BOOKMARK); + var bookmarkedCell = sq.getBody().querySelector("." + PASTE_TABLE_CELL_BOOKMARK); + + if (bookmarkedTable) { + removeClass_default()(bookmarkedTable, PASTE_TABLE_BOOKMARK); + range.setEndAfter(bookmarkedTable); + range.collapse(false); + sq.setSelection(range); + } + + if (bookmarkedCell) { + removeClass_default()(bookmarkedCell, PASTE_TABLE_CELL_BOOKMARK); + range.selectNodeContents(bookmarkedCell); + range.collapse(false); + sq.setSelection(range); + } + } + /** + * extend range if need + * @param {Range} range to extend + * @private + */ + ; + + _proto._extendRange = function _extendRange(range) { + // non-text node && not selected whole area, then expand the range + if (dom["a" /* default */].isTextNode(range.commonAncestorContainer) && (range.startOffset !== 0 || range.commonAncestorContainer.textContent.length !== range.endOffset) && range.commonAncestorContainer.nodeName !== 'TD') { + return; + } + + if (range.startOffset === 0) { + range = this._extendStartRange(range); + } + + if (range.endOffset === dom["a" /* default */].getOffsetLength(range.endContainer)) { + range = this._extendEndRange(range); + } // commonAncestor if all of it's children has been selected + + + if (this._isWholeCommonAncestorContainerSelected(range)) { + range.selectNode(range.commonAncestorContainer); + } + + this.wwe.getEditor().setSelection(range); + } + /** + * Extends current range's startContainer + * @param {Range} range Range object + * @returns {Range} + * @private + */ + ; + + _proto._extendStartRange = function _extendStartRange(range) { + var newBound = range.startContainer; // expand range + + while (newBound.parentNode !== range.commonAncestorContainer && newBound.parentNode !== this.wwe.getBody() && !newBound.previousSibling) { + newBound = newBound.parentNode; + } // expand range + + + range.setStart(newBound.parentNode, dom["a" /* default */].getNodeOffsetOfParent(newBound)); + return range; + } + /** + * Extends current range's endContainer + * @param {Range} range Range object + * @returns {Range} + * @private + */ + ; + + _proto._extendEndRange = function _extendEndRange(range) { + var newBound = range.endContainer; + var boundNext = newBound.nextSibling; // expand range + + while (newBound.parentNode !== range.commonAncestorContainer && newBound.parentNode !== this.wwe.getBody() && (!boundNext || dom["a" /* default */].getNodeName(boundNext) === 'BR' && newBound.parentNode.lastChild === boundNext)) { + newBound = newBound.parentNode; + boundNext = newBound.nextSibling; + } // expand range level + + + range.setEnd(newBound.parentNode, dom["a" /* default */].getNodeOffsetOfParent(newBound) + 1); + return range; + } + /** + * Check whether whole commonAncestorContainter textContent selected or not + * @param {Range} range Range object + * @returns {boolean} result + * @private + */ + ; + + _proto._isWholeCommonAncestorContainerSelected = function _isWholeCommonAncestorContainerSelected(range) { + return range.commonAncestorContainer.nodeType === Node.ELEMENT_NODE && range.commonAncestorContainer !== this.wwe.getBody() && range.startOffset === 0 && range.endOffset === range.commonAncestorContainer.childNodes.length && range.commonAncestorContainer === range.startContainer && range.commonAncestorContainer === range.endContainer; + }; + + return WwClipboardManager; +}(); + +/* harmony default export */ var wwClipboardManager = (wwClipboardManager_WwClipboardManager); +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/domUtil/hasClass.js +var hasClass = __webpack_require__(16); +var hasClass_default = /*#__PURE__*/__webpack_require__.n(hasClass); + +// CONCATENATED MODULE: ./src/js/wwLinkManager.js +/** + * @fileoverview Implements wysiwyg link manager + * @author NHN FE Development Lab + */ + + + +var CLASS_NAME_IMAGE_LINK = 'image-link'; +/** + * Class WwLinkManager + * @param {WysiwygEditor} wwe - WysiwygEditor instance + * @ignore + */ + +var wwLinkManager_WwLinkManager = /*#__PURE__*/function () { + function WwLinkManager(wwe) { + this.wwe = wwe; + this.eventManager = wwe.eventManager; + /** + * Name property + * @type {string} + */ + + this.name = 'link'; + + this._init(); + } + + var _proto = WwLinkManager.prototype; + + _proto._init = function _init() { + var _this = this; + + this.eventManager.listen('wysiwygSetValueAfter', function () { + _this._addClassNameToAllImageLinks(); + }); + this.wwe.getEditor().addEventListener('click', function (ev) { + var target = ev.target, + offsetX = ev.offsetX, + offsetY = ev.offsetY; + var popupButton = getComputedStyle(target, ':before'); + + if (hasClass_default()(target, CLASS_NAME_IMAGE_LINK) && dom["a" /* default */].isInsideButtonBox(popupButton, offsetX, offsetY)) { + _this._selectImageLink(target.parentNode); + + _this.eventManager.emit('openPopupAddLink', { + url: target.getAttribute('href') + }); + } + }); + }; + + _proto._selectImageLink = function _selectImageLink(imageLink) { + var range = this.wwe.getEditor().getSelection().cloneRange(); + range.selectNode(imageLink); + this.wwe.getEditor().setSelection(range); + }; + + _proto._addClassNameToImageLinks = function _addClassNameToImageLinks(links) { + links.forEach(function (link) { + if (link.firstChild && link.firstChild.nodeName === 'IMG') { + addClass_default()(link, CLASS_NAME_IMAGE_LINK); + } + }); + }; + + _proto._addClassNameToAllImageLinks = function _addClassNameToAllImageLinks() { + var links = dom["a" /* default */].findAll(this.wwe.getBody(), 'a'); + + this._addClassNameToImageLinks(links); + } + /** + * Add class name on all link including image in selection + */ + ; + + _proto.addClassNameToImageLinksInSelection = function addClassNameToImageLinksInSelection() { + var sq = this.wwe.getEditor(); + + var _sq$getSelection = sq.getSelection(), + container = _sq$getSelection.commonAncestorContainer; + + if (dom["a" /* default */].isElemNode(container)) { + var links; + + if (container.nodeName === 'A') { + links = [container]; + } else { + links = dom["a" /* default */].findAll(container, 'a'); + } + + this._addClassNameToImageLinks(links); + } + }; + + return WwLinkManager; +}(); + + +// CONCATENATED MODULE: ./src/js/wwListManager.js +/** + * @fileoverview Implements wysiwyg list manager + * @author NHN FE Development Lab + */ + + + +var FIND_LI_ELEMENT = /
  • ]*>)(.*?)(<\/(?:th|td)>)/g; +var FIND_LIST_OR_LIST_ITEM_TAG_RX = /<(ul|ol|li)([^>]*)>/g; +/** + * Class WwListManager + * @param {WysiwygEditor} wwe - WysiwygEditor instance + * @ignore + */ + +var wwListManager_WwListManager = /*#__PURE__*/function () { + function WwListManager(wwe) { + this.wwe = wwe; + this.eventManager = wwe.eventManager; + /** + * Name property + * @type {string} + */ + + this.name = 'list'; + + this._init(); + } + /** + * Initialize + * @private + */ + + + var _proto = WwListManager.prototype; + + _proto._init = function _init() { + this._initEvent(); + + this._initKeyHandler(); + } + /** + * Initialize event + * @private + */ + ; + + _proto._initEvent = function _initEvent() { + var _this = this; + + this.eventManager.listen('wysiwygSetValueBefore', function (html) { + return _this.convertToArbitraryNestingList(html); + }); + this.eventManager.listen('wysiwygRangeChangeAfter', function () { + _this._findAndRemoveEmptyList(); + + _this._removeBranchListAll(); + }); + this.eventManager.listen('wysiwygSetValueAfter', function () { + _this._removeBranchListAll(); + }); + this.eventManager.listen('wysiwygProcessHTMLText', function (html) { + html = _this._convertFromArbitraryNestingList(html); + return html; + }); + this.eventManager.listen('convertorBeforeHtmlToMarkdownConverted', function (html) { + return _this._insertDataToMarkPassForListInTable(html); + }); + }; + + _proto._initKeyHandler = function _initKeyHandler() { + var _this2 = this; + + this.wwe.addKeyEventHandler(['TAB', 'CTRL+]', 'META+]'], function (ev) { + var isNeedNext; + + if (_this2.wwe.getEditor().hasFormat('LI')) { + ev.preventDefault(); + + _this2.eventManager.emit('command', 'Indent'); + + isNeedNext = false; + } + + return isNeedNext; + }); + this.wwe.addKeyEventHandler(['SHIFT+TAB', 'CTRL+[', 'META+['], function (ev, range) { + var isNeedNext; + + if (_this2.wwe.getEditor().hasFormat('LI')) { + ev.preventDefault(); + var ul = dom["a" /* default */].children(dom["a" /* default */].closest(range.startContainer, 'li'), UL_OR_OL); + + _this2.eventManager.emit('command', 'Outdent'); + + if (ul.length && !ul.previousSibling) { + _this2._removeBranchList(ul); + } + + isNeedNext = false; + } + + return isNeedNext; + }); + this.wwe.addKeyEventHandler('ENTER', function (ev, range) { + if (range.collapsed) { + if (_this2.wwe.getEditor().hasFormat('LI')) { + _this2.wwe.defer(function () { + var afterRange = _this2.wwe.getRange(); + + var _domUtils$parents = dom["a" /* default */].parents(afterRange.startContainer, 'li'), + li = _domUtils$parents[0]; + + _this2._removeBranchListAll(li); + }); + } + } + }); + this.wwe.addKeyEventHandler('BACK_SPACE', function (ev, range) { + if (range.collapsed) { + if (_this2.wwe.getEditor().hasFormat('LI')) { + _this2.wwe.defer(function () { + _this2._removeBranchListAll(); + }); + } + } + }); + } + /** + * Find empty list for whole container and remove it. + * @private + */ + ; + + _proto._findAndRemoveEmptyList = function _findAndRemoveEmptyList() { + dom["a" /* default */].findAll(this.wwe.getBody(), UL_OR_OL).forEach(function (node) { + if (!FIND_LI_ELEMENT.test(node.innerHTML)) { + dom["a" /* default */].remove(node); + } + }); + } + /** + * Remove branch lists all from body + * @param {HTMLElement} root root to remove branch list + * @private + */ + ; + + _proto._removeBranchListAll = function _removeBranchListAll(root) { + var _this3 = this; + + root = !root ? this.wwe.getBody() : root; + dom["a" /* default */].findAll(root, 'li > ul, li > ol').forEach(function (node) { + if (!node || node.previousSibling) { + return; + } + + _this3._removeBranchList(node); + }); + } + /** + * Remove branch list of passed list(ul, ol) + * @param {HTMLElement} list list + * @private + */ + ; + + _proto._removeBranchList = function _removeBranchList(list) { + var branchRoot = list; + + while (!branchRoot.previousSibling && branchRoot.parentElement.tagName.match(/UL|OL|LI/g)) { + branchRoot = branchRoot.parentElement; + } + + var _domUtils$children = dom["a" /* default */].children(branchRoot, 'li'), + firstLi = _domUtils$children[0]; + + var unwrappedLIs = dom["a" /* default */].unwrap(list); + dom["a" /* default */].prepend(branchRoot, unwrappedLIs); + dom["a" /* default */].remove(firstLi); + } + /** + * make arbitrary nesting list out of standard list + * `
    • text
      • text2
    ` to + * `
    • text
      • text2
    ` + * @param {string} html string to convert + * @returns {string} converted HTML text + */ + ; + + _proto.convertToArbitraryNestingList = function convertToArbitraryNestingList(html) { + var NESTED_LIST_QUERY = 'li > ul, li > ol'; + var wrapper = dom["a" /* default */].createElementWith("
    " + html + "
    "); + var nestedList = wrapper.querySelector(NESTED_LIST_QUERY); + + while (nestedList !== null) { + var parentLI = nestedList.parentNode; + var parentList = parentLI.parentNode; + parentList.insertBefore(nestedList, parentLI.nextElementSibling); + nestedList = wrapper.querySelector(NESTED_LIST_QUERY); + } + + return wrapper.innerHTML; + } + /** + * make standard list out of arbitrary nesting list + * `
    • text
      • text2
    ` from + * `
    • text
      • text2
    ` + * @param {string} html string to convert + * @returns {string} converted HTML text + * @private + */ + ; + + _proto._convertFromArbitraryNestingList = function _convertFromArbitraryNestingList(html) { + var NESTED_LIST_QUERY = 'ol > ol, ol > ul, ul > ol, ul > ul'; + var wrapperDiv = dom["a" /* default */].createElementWith("
    " + html + "
    "); + var nestedList = wrapperDiv.querySelector(NESTED_LIST_QUERY); + + while (nestedList !== null) { + var prevLI = nestedList.previousElementSibling; + + while (prevLI && prevLI.tagName !== 'LI') { + prevLI = prevLI.previousElementSibling; + } + + if (prevLI) { + prevLI.appendChild(nestedList); + } else { + this._unwrap(nestedList); + } + + nestedList = wrapperDiv.querySelector(NESTED_LIST_QUERY); + } + + return wrapperDiv.innerHTML; + } + /** + * unwrap nesting list + * @param {Node} nestedList - nested list to unwrap + * @private + */ + ; + + _proto._unwrap = function _unwrap(nestedList) { + var fragment = document.createDocumentFragment(); + + while (nestedList.firstChild) { + fragment.appendChild(nestedList.firstChild); + } + + nestedList.parentNode.replaceChild(fragment, nestedList); + }; + + _proto._insertDataToMarkPassForListInTable = function _insertDataToMarkPassForListInTable(html) { + var replacedHtml = html.replace(FIND_CELL_TAG_RX, function (match, tdStart, tdContent, tdEnd) { + var content = tdContent.replace(FIND_LIST_OR_LIST_ITEM_TAG_RX, '<$1 data-tomark-pass $2>'); + return "" + tdStart + content + tdEnd; + }); + return replacedHtml; + } + /** + * Return lines in selection + * @param {Node} start Start element + * @param {Node} end End element + * @param {HTMLElement} body Editor body element + * @returns {Array.} + * @private + */ + ; + + _proto.getLinesOfSelection = function getLinesOfSelection(start, end) { + var lines = []; + var isLastLine = false; + var needNext = true; + var nextLine; + + if (dom["a" /* default */].isTextNode(start)) { + var _domUtils$parents2 = dom["a" /* default */].parents(start, DIV_OR_LI); + + start = _domUtils$parents2[0]; + } + + if (dom["a" /* default */].isTextNode(end)) { + var _domUtils$parents3 = dom["a" /* default */].parents(end, DIV_OR_LI); + + end = _domUtils$parents3[0]; + } + + for (var line = start; needNext; line = nextLine) { + if (matches_default()(line, DIV_OR_LI)) { + lines.push(line); + + if (line === end) { + isLastLine = true; + } else { + nextLine = this._getNextLine(line, end); + } + } else { + break; + } + + needNext = nextLine && !isLastLine; + } + + return lines; + } + /** + * get next line + * @param {Node} currentLine - current line node + * @param {Node} end - last node in selection + * @returns {Node} - next line node + * @private + */ + ; + + _proto._getNextLine = function _getNextLine(currentLine, end) { + var nextLine = currentLine.nextElementSibling; + + if (!nextLine) { + // current line was the last line in ul/ol + // while we have lines those has not been processed yet. + nextLine = currentLine.parentNode.nextElementSibling; + } else if (matches_default()(nextLine, UL_OR_OL)) { + // we don't sure firstChild is LI. arbtrary list can have another ol/ul + nextLine = nextLine.querySelector('li'); + } + + if (matches_default()(nextLine, DIV_OR_LI) || nextLine === end) { + return nextLine; + } + + return this._getNextLine(nextLine); + } + /** + * merge to previous list + * consider remove this function when https://github.com/neilj/Squire/issues/294 resolved + * @param {HTMLLIElement} currentLine - current li element + */ + ; + + _proto.mergeList = function mergeList(currentLine) { + var currentList = currentLine.parentNode; + var prevList = currentList.previousElementSibling; + var nextList = currentList.nextElementSibling; + + if (currentList.firstElementChild === currentLine) { + if (prevList && matches_default()(prevList, UL_OR_OL)) { + this._mergeList(currentList, prevList); + + currentList = prevList; + } + } + + if (currentList.lastElementChild === currentLine) { + if (nextList && matches_default()(nextList, UL_OR_OL)) { + this._mergeList(nextList, currentList); + } + } + } + /** + * merge list to targetList + * @param {HTMLOListElement|HTMLUListElement} list - list to merge + * @param {HTMLOListElement|HTMLUListElement} targetList - target list + * @private + */ + ; + + _proto._mergeList = function _mergeList(list, targetList) { + var listItem = list.firstElementChild; + + if (targetList && matches_default()(targetList, UL_OR_OL)) { + while (listItem) { + var temp = listItem.nextElementSibling; + targetList.appendChild(listItem); + listItem = temp; + } + + list.parentNode.removeChild(list); + } + } + /** + * Check whether is available to make List in table. + * @returns {boolean} - li element + */ + ; + + _proto.isAvailableMakeListInTable = function isAvailableMakeListInTable() { + var selectionManager = this.wwe.componentManager.getManager('tableSelection'); + var selectedCells = selectionManager.getSelectedCells(); + var sq = this.wwe.getEditor(); + return selectedCells && sq.hasFormat('table') && !sq.hasFormat('OL') && !sq.hasFormat('UL'); + } + /** + * Find parent node before TD + * @param {Node} node - startContainer or endContainer of range + * @param {Number} offset - offset + * @returns {Node} - parent node before TD + * @private + */ + ; + + _proto._getParentNodeBeforeTD = function _getParentNodeBeforeTD(node, offset) { + var parentNode = dom["a" /* default */].getParentUntil(node, 'TD'); + + if (!parentNode) { + var childNodes = node.childNodes; + var length = childNodes ? childNodes.length : 0; + var newOffset = offset > 0 && offset === length ? offset - 1 : offset; + parentNode = dom["a" /* default */].getChildNodeByOffset(node, newOffset); + } + + return parentNode; + } + /** + * Find LI node inside cell (TH, TD) + * If target node is not li and parents of taget node is not li, return null. + * @param {Node} targetNode - startContainer or endContainer of range + * @param {Number} offset - offset + * @returns {Node} - LI node or null + * @private + */ + ; + + _proto._findLINodeInsideCell = function _findLINodeInsideCell(targetNode, offset) { + var liNode = null; + + if (targetNode && dom["a" /* default */].isCellNode(targetNode)) { + targetNode = targetNode.firstChild; + } + + var liParent = dom["a" /* default */].getParentUntilBy(targetNode, function (parentNode) { + return parentNode && dom["a" /* default */].isListNode(parentNode); + }, function (parentNode) { + return parentNode && dom["a" /* default */].isCellNode(parentNode); + }); + + if (liParent) { + liNode = liParent; + } else if (targetNode.nodeName === 'LI') { + liNode = targetNode; + } else if (dom["a" /* default */].isListNode(targetNode)) { + var childLength = targetNode.childNodes.length; + liNode = targetNode.childNodes[offset >= childLength ? childLength - 1 : offset]; + } + + return liNode; + } + /** + * Get first node on the line where range start. + * @param {Node} targetNode - startContainer + * @param {Number} offset - startOffset + * @returns {Node} - first node where range start + * @private + */ + ; + + _proto._getFirstNodeInLineOfTable = function _getFirstNodeInLineOfTable(targetNode, offset) { + var startNode = this._findLINodeInsideCell(targetNode, offset); + + if (!startNode) { + startNode = this._getParentNodeBeforeTD(targetNode, offset); + var _startNode = startNode, + previousSibling = _startNode.previousSibling; + + while (previousSibling && previousSibling.nodeName !== 'BR' && !dom["a" /* default */].isListNode(previousSibling)) { + startNode = previousSibling; + previousSibling = startNode.previousSibling; + } + } + + return startNode; + } + /** + * Get last node on the line where range end. + * @param {Node} targetNode - endContainer + * @param {Number} offset - endOffset + * @returns {Node} - last node where range end + * @private + */ + ; + + _proto._getLastNodeInLineOfTable = function _getLastNodeInLineOfTable(targetNode, offset) { + var endNode = this._findLINodeInsideCell(targetNode, offset); + + if (!endNode) { + endNode = this._getParentNodeBeforeTD(targetNode, offset); + + while (endNode.nextSibling) { + if (endNode.nodeName === 'BR' || dom["a" /* default */].isListNode(endNode)) { + break; + } + + endNode = endNode.nextSibling; + } + } + + return endNode; + } + /** + * Check whether node is last node in the line of table + * If the node is li or br, the node is last node in the line of table. + * @param {node} node - node + * @returns {boolean} - whether node is last node in line of table + * @private + */ + ; + + _proto._isLastNodeInLineOfTable = function _isLastNodeInLineOfTable(node) { + var nodeName = node.nodeName; + return nodeName === 'LI' || nodeName === 'BR'; + } + /** + * Get next node in the line of table + * If current node is li node and nextSibling is not existing, next node is parent's nextSibling. + * If nextSibiling of node is a list node (UL or OL), next node is first child of the list node. + * @param {node} node - node + * @returns {node} - next node + * @private + */ + ; + + _proto._getNextNodeInLineOfTable = function _getNextNodeInLineOfTable(node) { + var nextSibling = node.nextSibling; + + if (node.nodeName === 'LI' && !nextSibling) { + var parentNode = node.parentNode; + + while (!dom["a" /* default */].isCellNode(parentNode)) { + if (parentNode.nextSibling) { + nextSibling = parentNode.nextSibling; + break; + } + + parentNode = parentNode.parentNode; + } + } else if (dom["a" /* default */].isListNode(nextSibling)) { + nextSibling = nextSibling.firstChild; + } + + return nextSibling; + } + /** + * get nodes in each lines of table + * @param {range} range - range + * @returns {array} - each nodes in line + * @private + */ + ; + + _proto._getLinesOfSelectionInTable = function _getLinesOfSelectionInTable(range) { + var startContainer = range.startContainer, + endContainer = range.endContainer, + startOffset = range.startOffset, + endOffset = range.endOffset; + + var firstNode = this._getFirstNodeInLineOfTable(startContainer, startOffset); + + var lastNode = this._getLastNodeInLineOfTable(endContainer, endOffset); + + var lines = []; + var oneLine = []; + + while (firstNode) { + oneLine.push(firstNode); + + if (this._isLastNodeInLineOfTable(firstNode)) { + lines.push(oneLine); + oneLine = []; + } + + if (firstNode === lastNode) { + if (oneLine.length) { + lines.push(oneLine); + } + + break; + } + + firstNode = this._getNextNodeInLineOfTable(firstNode); + } + + return lines; + } + /** + * create OL or UL element + * @param {string} listType - OL, UL or TASK + * @returns {Node} - OL or UL element + * @private + */ + ; + + _proto._createListElement = function _createListElement(listType) { + return document.createElement(listType === 'TASK' ? 'UL' : listType); + } + /** + * create li element + * @param {array} oneLineNodes - node array + * @param {string} listType - OL, UL or TASK + * @returns {Node} - li element + * @private + */ + ; + + _proto._createListItemElement = function _createListItemElement(oneLineNodes, listType) { + var liNode = document.createElement('li'); + oneLineNodes.forEach(function (node) { + liNode.appendChild(node); + }); + + if (listType === 'TASK') { + var taskManager = this.wwe.componentManager.getManager('task'); + taskManager.formatTask(liNode); + } + + return liNode; + }; + + _proto._mergeListWithPreviousSibiling = function _mergeListWithPreviousSibiling(node) { + var previousSibling = node.previousSibling; + var result = node; + + if (previousSibling && node.nodeName === previousSibling.nodeName) { + this._mergeList(node, previousSibling); + + result = previousSibling; + } + + return result; + }; + + _proto._mergeListWithNextSibiling = function _mergeListWithNextSibiling(node) { + var nextSibling = node.nextSibling; + + if (nextSibling && node.nodeName === nextSibling.nodeName) { + this._mergeList(nextSibling, node); + } + + return node; + } + /** + * make listNode (OL or UL) + * @param {range} range - range + * @param {staring} listType - UL, OL, TASK + * @returns {array} childNodes of list node (OL/UL) + */ + ; + + _proto.createListInTable = function createListInTable(range, listType) { + var _this4 = this; + + var lines = this._getLinesOfSelectionInTable(range); + + var lastLine = lines[lines.length - 1]; + var lastNode = lastLine[lastLine.length - 1]; + var nextNode = lastNode.nextSibling; + var parentNode = lastNode.parentNode; + + var listNode = this._createListElement(listType); + + var _listNode = listNode, + listNodeName = _listNode.nodeName; + var newLIs = []; + lines.forEach(function (oneLineNodes) { + var oneLineFirstNode = oneLineNodes[0]; + var liElement; // oneLineFirstNode was already a list item in the table + + if (oneLineFirstNode.nodeName === 'LI') { + var existingListNode = oneLineFirstNode.parentNode; + liElement = oneLineFirstNode; // If the existing list that is already in table is not same the list to be created, + // change the existing list to the list to be created + + if (existingListNode.nodeName !== listNodeName) { + var childNodes = existingListNode.childNodes; + toArray_default()(childNodes).forEach(function () { + listNode.appendChild(existingListNode.firstChild); + }); + existingListNode.parentNode.replaceChild(listNode, existingListNode); + } + + listNode = liElement.parentNode; + } else { + liElement = _this4._createListItemElement(oneLineNodes, listType); + listNode.appendChild(liElement); + } + + newLIs.push(liElement); + }); + + if (!listNode.parentNode) { + parentNode.insertBefore(listNode, nextNode); + } + + listNode = this._mergeListWithPreviousSibiling(listNode); + + this._mergeListWithNextSibiling(listNode); + + return newLIs; + } + /** + * adjust range for list node (OL/UL) + * according to origin startContainer and endContainer + * @param {node} startContainer - startContainer + * @param {node} endContainer - endContainer + * @param {number} startOffset - startOffset + * @param {number} endOffset - endOffset + * @param {array} listNode - node array + */ + ; + + _proto.adjustRange = function adjustRange(startContainer, endContainer, startOffset, endOffset, listNode) { + var newStartContainer = dom["a" /* default */].containsNode(listNode[0], startContainer) ? startContainer : listNode[0]; + var newEndContainer = dom["a" /* default */].containsNode(listNode[listNode.length - 1], endContainer) ? endContainer : listNode[listNode.length - 1]; + var newStartOffset = startContainer.nodeName === 'TD' ? 0 : startOffset; + var newEndOffset = endContainer.nodeName === 'TD' ? 0 : endOffset; + this.wwe.setSelectionByContainerAndOffset(newStartContainer, newStartOffset, newEndContainer, newEndOffset); + }; + + return WwListManager; +}(); + +/* harmony default export */ var wwListManager = (wwListManager_WwListManager); +// CONCATENATED MODULE: ./src/js/wwTaskManager.js +/** + * @fileoverview Implements wysiwyg task manager + * @author NHN FE Development Lab + */ + + + + +var TASK_CLASS_NAME = 'task-list-item'; +var TASK_ATTR_NAME = 'data-te-task'; +var TASK_CHECKED_CLASS_NAME = 'checked'; +/** + * Class WwTaskManager + * @param {WysiwygEditor} wwe - WysiwygEditor instance + * @ignore + */ + +var wwTaskManager_WwTaskManager = /*#__PURE__*/function () { + function WwTaskManager(wwe) { + this.wwe = wwe; + this.eventManager = wwe.eventManager; + /** + * Name property + * @type {string} + */ + + this.name = 'task'; + + this._init(); + } + /** + * Init + * @private + */ + + + var _proto = WwTaskManager.prototype; + + _proto._init = function _init() { + this._initKeyHandler(); + + this._initEvent(); + + this.wwe.getEditor().addEventListener('mousedown', function (ev) { + var style = getComputedStyle(ev.target, ':before'); + + if (ev.target.hasAttribute(TASK_ATTR_NAME) && dom["a" /* default */].isInsideButtonBox(style, ev.offsetX, ev.offsetY)) { + // Prevent cursor focusing + ev.preventDefault(); + dom["a" /* default */].toggleClass(ev.target, TASK_CHECKED_CLASS_NAME); + } + }); + } + /** + * Initialize event + * @private + */ + ; + + _proto._initEvent = function _initEvent() { + var _this = this; + + this.eventManager.listen('wysiwygSetValueAfter', function () { + _this._removeTaskListClass(); + }); + } + /** + * Initialize key event handler + * @private + */ + ; + + _proto._initKeyHandler = function _initKeyHandler() { + var _this2 = this; + + this.wwe.addKeyEventHandler('ENTER', function (ev, range) { + if (_this2.isInTaskList(range)) { + _this2.wwe.defer(function () { + var newRange = _this2.wwe.getRange(); + + var li = dom["a" /* default */].closest(newRange.startContainer, 'li'); + + if (li) { + removeClass_default()(li, TASK_CHECKED_CLASS_NAME); + } + }); + } + }); + } + /** + * Check whether passed range is in task list or not + * @param {Range} range range + * @returns {boolean} result + */ + ; + + _proto.isInTaskList = function isInTaskList(range) { + var li; + + if (!range) { + range = this.wwe.getEditor().getSelection().cloneRange(); + } + + if (range.startContainer.nodeType === Node.ELEMENT_NODE && range.startContainer.tagName === 'LI') { + li = range.startContainer; + } else { + var _domUtils$parents = dom["a" /* default */].parents(range.startContainer, 'li'); + + li = _domUtils$parents[0]; + } + + return !!li && hasClass_default()(li, TASK_CLASS_NAME); + } + /** + * Unforamt task + * @param {Node} node target + */ + ; + + _proto.unformatTask = function unformatTask(node) { + var li = dom["a" /* default */].closest(node, 'li'); + removeClass_default()(li, TASK_CLASS_NAME); + removeClass_default()(li, TASK_CHECKED_CLASS_NAME); + li.removeAttribute(TASK_ATTR_NAME); + + if (!li.getAttribute('class')) { + li.removeAttribute('class'); + } + } + /** + * Format task + * @param {Node} node target + */ + ; + + _proto.formatTask = function formatTask(node) { + var li = dom["a" /* default */].closest(node, 'li'); + addClass_default()(li, TASK_CLASS_NAME); + li.setAttribute(TASK_ATTR_NAME, ''); + } + /** + * Format task if current range has task class name + * @private + */ + ; + + _proto._formatTaskIfNeed = function _formatTaskIfNeed() { + var range = this.wwe.getEditor().getSelection().cloneRange(); + + if (this.isInTaskList(range)) { + this.formatTask(range.startContainer); + } + } + /** + * Remove tasklist class + * @private + */ + ; + + _proto._removeTaskListClass = function _removeTaskListClass() { + // because task-list class is block merge normal list and task list + dom["a" /* default */].findAll(this.wwe.getBody(), '.task-list').forEach(function (node) { + removeClass_default()(node, 'task-list'); + }); + }; + + return WwTaskManager; +}(); + +/* harmony default export */ var wwTaskManager = (wwTaskManager_WwTaskManager); +// CONCATENATED MODULE: ./src/js/wwTableManager.js +/** + * @fileoverview Implements wysiwyg table manager + * @author NHN FE Development Lab + */ + + + + + + +var isIE10 = browser_default.a.msie && browser_default.a.version === 10; +var TABLE_CLASS_PREFIX = 'te-content-table-'; +var isIE10And11 = browser_default.a.msie && (browser_default.a.version === 10 || browser_default.a.version === 11); +var BASIC_CELL_CONTENT = browser_default.a.msie ? '' : '
    '; +var TABLE_CELL_SELECTED_CLASS_NAME = 'te-cell-selected'; +/** + * Class WwTableManager + * @param {WysiwygEditor} wwe - WysiwygEditor instance + * @ignore + */ + +var wwTableManager_WwTableManager = /*#__PURE__*/function () { + function WwTableManager(wwe) { + this.wwe = wwe; + this.eventManager = wwe.eventManager; + /** + * Name property + * @type {string} + */ + + this.name = 'table'; + this._lastCellNode = null; + + this._init(); + } + /** + * Initialize + * @private + */ + + + var _proto = WwTableManager.prototype; + + _proto._init = function _init() { + this._initKeyHandler(); + + this._initEvent(); + + this.tableID = 0; + } + /** + * Initialize event + * @private + */ + ; + + _proto._initEvent = function _initEvent() { + var _this = this; + + this.eventManager.listen('wysiwygRangeChangeAfter.table', function () { + var range = _this.wwe.getEditor().getSelection(); + + var isRangeInTable = _this.wwe.isInTable(range); + + _this._unwrapBlockInTable(); + + _this._completeTableIfNeed(); + + if (!isRangeInTable) { + var selectionManager = _this.wwe.componentManager.getManager('tableSelection'); + + selectionManager.removeClassAttrbuteFromAllCellsIfNeed(); + } + + _this._insertDefaultBlockBetweenTable(); + }); + this.eventManager.listen('wysiwygSetValueAfter.table', function () { + _this._unwrapBlockInTable(); + + _this._insertDefaultBlockBetweenTable(); + }); // remove last br in td or th + + this.eventManager.listen('wysiwygProcessHTMLText.table', function (html) { + return html.replace(/
    (<\/td>|<\/th>)/g, '$1'); + }); + this.eventManager.listen('cut.table', function () { + var selectionManager = _this.wwe.componentManager.getManager('tableSelection'); + + var selectedCells = selectionManager.getSelectedCells(); + + if (selectedCells.length) { + selectedCells.forEach(function (cell) { + cell.innerHTML = BASIC_CELL_CONTENT; + }); + } + + selectionManager.removeClassAttrbuteFromAllCellsIfNeed(); + }); + this.eventManager.listen('copyBefore.table', function (_ref) { + var clipboardContainer = _ref.clipboardContainer; + return _this.updateTableHtmlOfClipboardIfNeed(clipboardContainer); + }); + } + /** + * Update table html of clipboard data, if has selected cells. + * @param {HTMLElement} clipboardContainer - clipboard element + */ + ; + + _proto.updateTableHtmlOfClipboardIfNeed = function updateTableHtmlOfClipboardIfNeed(clipboardContainer) { + var _this2 = this; + + var selectionManager = this.wwe.componentManager.getManager('tableSelection'); + var selectedCells = selectionManager.getSelectedCells(); + + if (selectedCells.length) { + selectionManager.createRangeBySelectedCells(); + var fragment = this.wwe.getEditor().getSelection().cloneContents(); + toArray_default()(fragment.children).forEach(function (node) { + if (!_this2.isTableOrSubTableElement(node.nodeName)) { + return; + } + + if (node.nodeName === 'TABLE' && node.querySelector('thead') && node.querySelector('tbody')) { + dom["a" /* default */].remove(node); + } else if (node.previousSibling && node.previousSibling.nodeName === 'TABLE') { + node.previousSibling.appendChild(node); + } else { + _this2._completeIncompleteTable(node); + + if (node.nodeName !== 'TABLE' && node.nodeName !== 'THEAD') { + var thead = dom["a" /* default */].closest(node, 'table').querySelector('thead'); + dom["a" /* default */].remove(thead); + } + } + }); + clipboardContainer.appendChild(fragment); + dom["a" /* default */].findAll(clipboardContainer, "." + TABLE_CELL_SELECTED_CLASS_NAME).forEach(function (cell) { + removeClass_default()(cell, TABLE_CELL_SELECTED_CLASS_NAME); + }); + } + } + /** + * Paste clibpard data that contains only table. + * @param {Node} clipboardTable - table element of clipboard + */ + ; + + _proto.pasteTableData = function pasteTableData(clipboardTable) { + this._expandTableIfNeed(clipboardTable); + + this._pasteDataIntoTable(clipboardTable); + } + /** + * Initialize key event handler + * @private + */ + ; + + _proto._initKeyHandler = function _initKeyHandler() { + var _this3 = this; + + this.keyEventHandlers = { + DEFAULT: function DEFAULT(ev, range, keymap) { + var isRangeInTable = _this3.wwe.isInTable(range); + + if (isRangeInTable && !_this3._isModifierKey(keymap)) { + _this3._recordUndoStateIfNeed(range); + + _this3._removeContentsAndChangeSelectionIfNeed(range, keymap, ev); + } else if (!isRangeInTable && _this3._lastCellNode) { + _this3._recordUndoStateAndResetCellNode(range); + } + + if (isRangeInTable && !_this3._isModifierKeyPushed(ev)) { + _this3.wwe.getEditor().modifyDocument(function () { + var selectionManager = _this3.wwe.componentManager.getManager('tableSelection'); + + selectionManager.removeClassAttrbuteFromAllCellsIfNeed(); + }); + } + }, + ENTER: function ENTER(ev, range) { + var isNeedNext; + + if (_this3._isAfterTable(range)) { + ev.preventDefault(); + range.setStart(range.startContainer, range.startOffset - 1); + + _this3.wwe.breakToNewDefaultBlock(range); + + isNeedNext = false; + } else if (_this3._isBeforeTable(range)) { + ev.preventDefault(); + + _this3.wwe.breakToNewDefaultBlock(range, 'before'); + + isNeedNext = false; + } else if (_this3.wwe.isInTable(range)) { + if (!_this3._isInList(range.startContainer) && _this3._isInStyledText(range)) { + _this3.wwe.defer(function () { + _this3._removeBRinStyleText(); + }); + } else if (_this3._isEmptyFirstLevelLI(range)) { + _this3.wwe.defer(function () { + // Squire make div when LI level is decreased in first level so should replace div to br + var afterRange = _this3.wwe.getRange().cloneRange(); + + var div = afterRange.startContainer; + var br = document.createElement('br'); + div.parentNode.replaceChild(br, div); + afterRange.setStartBefore(br); + afterRange.collapse(true); + + _this3.wwe.getEditor().setSelection(afterRange); + }); + } + + _this3._appendBrIfTdOrThNotHaveAsLastChild(range); + + isNeedNext = false; + } + + return isNeedNext; + }, + BACK_SPACE: function BACK_SPACE(ev, range, keymap) { + return _this3._handleBackspaceAndDeleteKeyEvent(ev, range, keymap); + }, + DELETE: function DELETE(ev, range, keymap) { + return _this3._handleBackspaceAndDeleteKeyEvent(ev, range, keymap); + }, + TAB: function TAB() { + return _this3._moveCursorTo('next', 'cell'); + }, + 'SHIFT+TAB': function SHIFTTAB(ev) { + return _this3._moveCursorTo('previous', 'cell', ev); + }, + UP: function UP(ev) { + return _this3._moveCursorTo('previous', 'row', ev); + }, + DOWN: function DOWN(ev) { + return _this3._moveCursorTo('next', 'row', ev); + } + }; + forEachOwnProperties_default()(this.keyEventHandlers, function (handler, key) { + return _this3.wwe.addKeyEventHandler(key, handler); + }); + } + /** + * Check whether node is li and empty + * @param {node} node node + * @returns {boolean} whether node is li and empty + * @private + */ + ; + + _proto._isEmptyListItem = function _isEmptyListItem(node) { + var childNodes = node.childNodes, + nodeName = node.nodeName; + return nodeName === 'LI' && childNodes.length === 1 && childNodes[0].nodeName === 'BR'; + } + /** + * Check whether range is in empty LI that is first level + * @param {range} range range + * @returns {boolean} whether range is in empty LI that is first level + * @private + */ + ; + + _proto._isEmptyFirstLevelLI = function _isEmptyFirstLevelLI(range) { + var collapsed = range.collapsed, + startContainer = range.startContainer, + startOffset = range.startOffset; + return collapsed && startOffset === 0 && this._isEmptyListItem(startContainer) && dom["a" /* default */].isFirstLevelListItem(startContainer); + } + /** + * Check whether range is in style tag that is like 'B', 'I', 'S', 'SPAN', 'CODE' + * Those tag is supported in Wysiwyg. + * @param {Range} range range + * @returns {Boolean} range is in the style tag + * @private + */ + ; + + _proto._isInStyledText = function _isInStyledText(range) { + var startContainer = range.startContainer; + var node; + + if (dom["a" /* default */].isTextNode(startContainer)) { + node = startContainer.parentNode; + } else { + node = startContainer; + } + + return range.collapsed && dom["a" /* default */].isStyledNode(node); + } + /** + * When enter key occur in the styled text, 'br' tag insert in the style tag like 'b', 'i' etc. + * So in thoes case, 'br' tag would be pulled out in this logic. + * @private + */ + ; + + _proto._removeBRinStyleText = function _removeBRinStyleText() { + var afterRange = this.wwe.getRange(); + var startContainer = afterRange.startContainer, + startOffset = afterRange.startOffset; + var styleNode; + + if (startContainer.nodeName === 'TD') { + // This case is TEST
    |
    + styleNode = dom["a" /* default */].getChildNodeByOffset(startContainer, startOffset - 1); + } else { + styleNode = dom["a" /* default */].getParentUntil(startContainer, 'TD'); + } + + var brNode = styleNode.querySelector('br'); + + if (!brNode) { + return; + } + + var _styleNode = styleNode, + tdNode = _styleNode.parentNode, + nodeName = _styleNode.nodeName; + + if (nodeName === 'CODE' && !brNode.previousSibling) { + // cursor is located in the start of text + // Before Enter : |TEST + // After Enter :
    |TEST
    + // TO BE :
    |TEST + tdNode.insertBefore(brNode, styleNode); + afterRange.setStart(styleNode, 0); + } else if (nodeName === 'CODE' && !brNode.nextSibling) { + // cursor is located in the end of text + // Before Enter : TEST| + // After Enter : TEST
    |
    + // TO BE : TEST
    | + tdNode.insertBefore(brNode, styleNode.nextSibling); + afterRange.setStart(tdNode, dom["a" /* default */].getNodeOffsetOfParent(brNode) + 1); + } else { + // [Case 1] cursor is located in the middle of text + // Before Enter : TE|ST + // After Enter : TE
    |ST
    + // TO BE : TE
    |ST + // [Case 2] cursor is located in the start of text + // Before Enter : |TEST + // After Enter :
    |TEST
    + // TO BE : |
    TEST + // [Case 3] cursor is located in the end of text + // Before Enter : TEST| + // After Enter : TEST
    |
    + // TO BE : TEST
    | + var newNode = this._splitByBR(styleNode, brNode); + + afterRange.setStart(newNode, 0); + } + + afterRange.collapse(true); + this.wwe.getEditor().setSelection(afterRange); + } + /** + * When container node have br node, split container base on br node and pull out BR. + * After Enter : TE
    ST
    + * TO BE : TE
    ST + * @param {Node} container container + * @param {Node} brNode container + * @returns {Node} node for positioning of cursor + * @private + */ + ; + + _proto._splitByBR = function _splitByBR(container, brNode) { + var cloneStyleNode = container.cloneNode(true); + var newBR = document.createElement('br'); + var parentNode = container.parentNode; // Origin style node should be removed the back nodes of br node. + + dom["a" /* default */].removeNodesByDirection(container, brNode, false); + brNode.parentNode.removeChild(brNode); // Cloned style node should be removed the front nodes of br node + + var clonedBR = cloneStyleNode.querySelector('br'); + dom["a" /* default */].removeNodesByDirection(cloneStyleNode, clonedBR, true); + clonedBR.parentNode.removeChild(clonedBR); + parentNode.insertBefore(cloneStyleNode, container.nextSibling); + parentNode.insertBefore(newBR, cloneStyleNode); + var leafNode = dom["a" /* default */].getLeafNode(cloneStyleNode); + + if (!dom["a" /* default */].getTextLength(leafNode)) { + leafNode.textContent = "\u200B"; + } + + return leafNode; + } + /** + * Check whether passed range is right before table or not + * @param {Range} range range + * @returns {boolean} result + * @private + */ + ; + + _proto._isBeforeTable = function _isBeforeTable(range) { + return dom["a" /* default */].getNodeName(dom["a" /* default */].getChildNodeByOffset(range.startContainer, range.startOffset)) === 'TABLE'; + } + /** + * Check whether passed range is right after table or not + * @param {Range} range range + * @returns {boolean} result + * @private + */ + ; + + _proto._isAfterTable = function _isAfterTable(range) { + var prevElem = dom["a" /* default */].getPrevOffsetNodeUntil(range.startContainer, range.startOffset); + return dom["a" /* default */].getNodeName(prevElem) === 'TABLE' && range.commonAncestorContainer === this.wwe.getBody(); + } + /** + * Handle backspace and delete key event + * @param {object} ev - Event object + * @param {Range} range - Range Object + * @param {string} keymap - keymap + * @returns {boolean} - need next + * @private + */ + ; + + _proto._handleBackspaceAndDeleteKeyEvent = function _handleBackspaceAndDeleteKeyEvent(ev, range, keymap) { + var isBackspace = keymap === 'BACK_SPACE'; + var selectionManager = this.wwe.componentManager.getManager('tableSelection'); + var selectedCells = selectionManager.getSelectedCells(); + var isNeedNext = true; + + if (range.collapsed) { + if (this.wwe.isInTable(range)) { + if (isBackspace) { + this._tableHandlerOnBackspace(range, ev); + } else { + this._tableHandlerOnDelete(range, ev); + } + + this._removeContentsAndChangeSelectionIfNeed(range, keymap, ev); + + isNeedNext = false; + } else if (!isBackspace && this._isBeforeTable(range) || isBackspace && this._isAfterTable(range)) { + ev.preventDefault(); + var startOffset = isBackspace ? range.startOffset - 1 : range.startOffset; + + this._removeTable(range, dom["a" /* default */].getChildNodeByOffset(range.startContainer, startOffset)); + + isNeedNext = false; + } + } else if (this.wwe.isInTable(range)) { + if (selectedCells.length > 0) { + var removed = this._removeContentsAndChangeSelectionIfNeed(range, keymap, ev); + + if (removed) { + ev.preventDefault(); + isNeedNext = false; + } + } + } + + return isNeedNext; + } + /** + * Move Li node to previous node that is previous node of list node. + * @param {node} liNode li node + * @param {range} range range + * @private + */ + ; + + _proto._moveListItemToPreviousOfList = function _moveListItemToPreviousOfList(liNode, range) { + var listNode = liNode.parentNode, + firstChild = liNode.firstChild; + var fragment = document.createDocumentFragment(); + dom["a" /* default */].mergeNode(liNode, fragment); + listNode.parentNode.insertBefore(fragment, listNode); + range.setStart(firstChild, 0); + range.collapse(true); + this.wwe.getEditor().setSelection(range); + + if (!listNode.hasChildNodes()) { + listNode.parentNode.removeChild(listNode); + } + }; + + _proto._isInList = function _isInList(targetNode) { + return dom["a" /* default */].getParentUntilBy(targetNode, function (node) { + return node && (dom["a" /* default */].isListNode(node) || node.nodeName === 'LI'); + }, function (node) { + return node && (node.nodeName === 'TD' || node.nodeName === 'TH'); + }); + } + /** + * Find LI node while search parentNode inside TD + * @param {node} startContainer startContainer + * @returns {node} liNode or null + * @private + */ + ; + + _proto._findListItem = function _findListItem(startContainer) { + return dom["a" /* default */].getParentUntilBy(startContainer, function (node) { + return node && dom["a" /* default */].isListNode(node); + }, function (node) { + return node && (node.nodeName === 'TD' || node.nodeName === 'TH'); + }); + } + /** + * Backspace handler in table + * @param {Range} range range + * @param {Event} event event + * @private + */ + ; + + _proto._tableHandlerOnBackspace = function _tableHandlerOnBackspace(range, event) { + var startContainer = range.startContainer, + startOffset = range.startOffset; + + var liNode = this._findListItem(startContainer); + + if (liNode && startOffset === 0 && dom["a" /* default */].isFirstListItem(liNode) && dom["a" /* default */].isFirstLevelListItem(liNode)) { + this.wwe.getEditor().saveUndoState(range); + + this._moveListItemToPreviousOfList(liNode, range); + + event.preventDefault(); + } else { + var prevNode = dom["a" /* default */].getPrevOffsetNodeUntil(startContainer, startOffset, 'TR'); + var prevNodeName = dom["a" /* default */].getNodeName(prevNode); + + if (prevNodeName === 'BR' && prevNode.parentNode.childNodes.length !== 1) { + event.preventDefault(); + dom["a" /* default */].remove(prevNode); + } + } + } + /** + * Return whether delete br in the br + * @param {Range} range Range object + * @returns {boolean} + * @private + */ + ; + + _proto._isDeletingBR = function _isDeletingBR(range) { + var currentNode = this._getCurrentNodeInCell(range); + + var nextSibling = currentNode && currentNode.nextSibling; + return dom["a" /* default */].getNodeName(currentNode) === 'BR' && !!nextSibling && dom["a" /* default */].getNodeName(nextSibling) === 'BR'; + }; + + _proto._getCurrentNodeInCell = function _getCurrentNodeInCell(range) { + var startContainer = range.startContainer, + startOffset = range.startOffset; + var currentNode; + + if (dom["a" /* default */].getNodeName(startContainer) === 'TD') { + currentNode = dom["a" /* default */].getChildNodeByOffset(startContainer, startOffset); + } else if (dom["a" /* default */].getParentUntil(startContainer, 'TD')) { + currentNode = startContainer; + } + + return currentNode; + } + /** + * Check whether range is located in end of the list + * @param {Node} liNode liNode + * @param {Range} range range + * @returns {Boolean} whether range is located in end of the list + * @private + */ + ; + + _proto._isEndOfList = function _isEndOfList(liNode, range) { + var startContainer = range.startContainer, + startOffset = range.startOffset; + var result = false; + + if (!liNode.nextSibling) { + if (liNode === startContainer) { + var liNodeOffset = dom["a" /* default */].getOffsetLength(liNode); + + if (liNode.lastChild.nodeName === 'BR') { + liNodeOffset -= 1; + } + + result = liNodeOffset === startOffset; + } else { + var parentNode = dom["a" /* default */].getParentUntil(startContainer, 'li') || startContainer; + var startContainerOffset = dom["a" /* default */].getOffsetLength(startContainer); + var lastChild = liNode.lastChild; + + if (lastChild.nodeName === 'BR') { + lastChild = lastChild.previousSibling; + } + + result = lastChild === parentNode && startContainerOffset === startOffset; + } + } + + return result; + } + /** + * Get next line nodes from target node + * @param {Node} node target node + * @returns {DocumentFragment} next line nodes + * @private + */ + ; + + _proto._getNextLineNode = function _getNextLineNode(node) { + var fragment = document.createDocumentFragment(); + var parentNode = dom["a" /* default */].getParentUntil(node, 'TD'); + var nextSibling = parentNode.nextSibling; + + while (nextSibling) { + var _nextSibling = nextSibling, + next = _nextSibling.nextSibling; + fragment.appendChild(nextSibling); + + if (nextSibling.nodeName === 'BR') { + break; + } + + nextSibling = next; + } + + return fragment; + } + /** + * Delete handler in table + * @param {Range} range range + * @param {Event} event event + * @private + */ + ; + + _proto._tableHandlerOnDelete = function _tableHandlerOnDelete(range, event) { + var liNode = this._findListItem(range.startContainer); + + if (liNode && this._isEndOfList(liNode, range)) { + this.wwe.getEditor().saveUndoState(range); + + if (liNode.lastChild.nodeName === 'BR') { + liNode.removeChild(liNode.lastChild); + } + + dom["a" /* default */].mergeNode(this._getNextLineNode(liNode), liNode); + event.preventDefault(); + } else if (this._isDeletingBR(range)) { + var currentNode = this._getCurrentNodeInCell(range); + + currentNode.parentNode.removeChild(currentNode.nextSibling); + event.preventDefault(); + } + } + /** + * Append br if td or th doesn't have br as last child + * @param {Range} range range + * @private + */ + ; + + _proto._appendBrIfTdOrThNotHaveAsLastChild = function _appendBrIfTdOrThNotHaveAsLastChild(range) { + var startContainerNodeName = dom["a" /* default */].getNodeName(range.startContainer); + var tdOrTh; + + if (startContainerNodeName === 'TD' || startContainerNodeName === 'TH') { + tdOrTh = range.startContainer; + } else { + var paths = dom["a" /* default */].parentsUntil(range.startContainer, 'tr'); + tdOrTh = paths[paths.length - 1]; + } + + var nodeName = dom["a" /* default */].getNodeName(tdOrTh.lastChild); + + if (nodeName !== 'BR' && nodeName !== 'DIV' && nodeName !== 'UL' && nodeName !== 'OL' && !isIE10And11) { + dom["a" /* default */].append(tdOrTh, '
    '); + } + } + /** + * Unwrap default block tag in table + * For Squire default action making abnormal behavior, remove default blocks in Table after setValue() called + * @private + */ + ; + + _proto._unwrapBlockInTable = function _unwrapBlockInTable() { + var blocks = dom["a" /* default */].findAll(this.wwe.getBody(), 'td div,th div,tr>br,td>br,th>br'); + blocks.forEach(function (node) { + if (dom["a" /* default */].getNodeName(node) === 'BR') { + var parentNodeName = dom["a" /* default */].getNodeName(node.parentNode); + var isInTableCell = /TD|TH/.test(parentNodeName); + var isEmptyTableCell = node.parentNode.textContent.length === 0; + var isLastBR = node.parentNode.lastChild === node; + + if (parentNodeName === 'TR' || isInTableCell && !isEmptyTableCell && isLastBR) { + dom["a" /* default */].remove(node); + } + } else { + dom["a" /* default */].unwrap(node); + } + }); + } + /** + * Insert default block between table element + * @private + */ + ; + + _proto._insertDefaultBlockBetweenTable = function _insertDefaultBlockBetweenTable() { + var tables = dom["a" /* default */].findAll(this.wwe.getBody(), 'table'); + tables.forEach(function (node) { + if (node.nextElementSibling && node.nextElementSibling.nodeName === 'TABLE') { + var insertedElement = document.createElement('div'); + insertedElement.appendChild(document.createElement('br')); + dom["a" /* default */].insertAfter(insertedElement, node); + } + }); + } + /** + * Remove table + * @param {Range} range range + * @param {Node} table table + * @private + */ + ; + + _proto._removeTable = function _removeTable(range, table) { + if (table.tagName === 'TABLE') { + this.wwe.getEditor().saveUndoState(range); + this.wwe.saveSelection(range); + dom["a" /* default */].remove(table); + this.wwe.restoreSavedSelection(); + } + } + /** + * record undo state if need + * @param {Range} range range + * @private + */ + ; + + _proto._recordUndoStateIfNeed = function _recordUndoStateIfNeed(range) { + var currentCellNode = dom["a" /* default */].getParentUntil(range.startContainer, 'TR'); + + if (range.collapsed && currentCellNode && this._lastCellNode !== currentCellNode) { + this.wwe.getEditor().saveUndoState(range); + this._lastCellNode = currentCellNode; + } + } + /** + * record undo state and reset last cell node + * @param {Range} range range + * @private + */ + ; + + _proto._recordUndoStateAndResetCellNode = function _recordUndoStateAndResetCellNode(range) { + this.wwe.getEditor().saveUndoState(range); + this.resetLastCellNode(); + } + /** + * Paste table data into table element + * @param {DocumentFragment} fragment Fragment of table element within + * @private + */ + ; + + _proto._pasteDataIntoTable = function _pasteDataIntoTable(fragment) { + var _this$wwe$getEditor$g = this.wwe.getEditor().getSelection(), + startContainer = _this$wwe$getEditor$g.startContainer; + + var tableData = this._getTableDataFromTable(fragment); + + var isTableCell = startContainer.nodeName === 'TD' || startContainer.nodeName === 'TH'; + var brString = isIE10 ? '' : '
    '; + var anchorElement, td, tr, tdContent; + + if (isTableCell) { + anchorElement = startContainer; + } else { + anchorElement = dom["a" /* default */].getParentUntilBy(startContainer, function (node) { + return node && (node.nodeName === 'TD' || node.nodeName === 'TH'); + }, function (node) { + return !!dom["a" /* default */].closest(node, 'table'); + }); + anchorElement = anchorElement ? anchorElement.parentNode : null; + } + + anchorElement = anchorElement ? anchorElement : startContainer.querySelector('th,td'); + td = anchorElement; + + while (tableData.length) { + tr = tableData.shift(); + + while (td && tr.length) { + tdContent = tr.shift(); + + if (tdContent.length) { + td.textContent = tdContent; + } else { + td.innerHTML = brString; + } + + td = dom["a" /* default */].getTableCellByDirection(td, 'next'); + } + + td = dom["a" /* default */].getSiblingRowCellByDirection(anchorElement, 'next', false); + anchorElement = td; + } + } + /** + * Get array data from table element + * @param {DocumentFragment} fragment table element + * @returns {Array} + * @private + */ + ; + + _proto._getTableDataFromTable = function _getTableDataFromTable(fragment) { + var tableData = []; + dom["a" /* default */].findAll(fragment, 'tr').forEach(function (tr) { + var trData = []; + toArray_default()(tr.children).forEach(function (cell) { + trData.push(cell.textContent); + }); + + if (trData.length) { + tableData.push(trData); + } + }); + return tableData; + } + /** + * Remove selected table contents + * @param {HTMLElement} selectedCells Selected cells + * @private + */ + ; + + _proto._removeTableContents = function _removeTableContents(selectedCells) { + this.wwe.getEditor().saveUndoState(); + toArray_default()(selectedCells).forEach(function (cell) { + var brHTMLString = isIE10 ? '' : '
    '; + cell.innerHTML = brHTMLString; + }); + } + /** + * Wrap dangling table cells with new TR + * @param {HTMLElement} container - clipboard container + * @returns {HTMLElement|null} + */ + ; + + _proto.wrapDanglingTableCellsIntoTrIfNeed = function wrapDanglingTableCellsIntoTrIfNeed(container) { + var danglingTableCells = dom["a" /* default */].children(container, 'td,th'); + var tr; + + if (danglingTableCells.length) { + var wrapperTr = document.createElement('tr'); + toArray_default()(danglingTableCells).forEach(function (cell) { + dom["a" /* default */].append(wrapperTr, cell); + }); + tr = wrapperTr; + } + + return tr; + } + /** + * Wrap TRs with new TBODY + * @param {HTMLElement} container - clipboard container + * @returns {HTMLElement|null} + */ + ; + + _proto.wrapTrsIntoTbodyIfNeed = function wrapTrsIntoTbodyIfNeed(container) { + var danglingTrs = dom["a" /* default */].children(container, 'tr'); + var ths = []; + toArray_default()(danglingTrs).forEach(function (tr) { + ths = ths.concat(tr.querySelectorAll('th')); + }); + var tbody; + + if (ths.length) { + toArray_default()(ths).forEach(function (node) { + var td = document.createElement('td'); + td.innerHTML = node.innerHTML; + dom["a" /* default */].insertBefore(node, td); + dom["a" /* default */].remove(node); + }); + } + + if (danglingTrs.length) { + var wrapperTableBody = document.createElement('tbody'); + toArray_default()(danglingTrs).forEach(function (tr) { + dom["a" /* default */].append(wrapperTableBody, tr); + }); + tbody = wrapperTableBody; + } + + return tbody; + } + /** + * Wrap THEAD followed by TBODY both into Table + * @param {HTMLElement} container - clipboard container + * @returns {HTMLElement|null} + */ + ; + + _proto.wrapTheadAndTbodyIntoTableIfNeed = function wrapTheadAndTbodyIntoTableIfNeed(container) { + var danglingThead = dom["a" /* default */].children(container, 'thead'); + var danglingTbody = dom["a" /* default */].children(container, 'tbody'); + var wrapperTable = document.createElement('table'); + var table; + + if (!danglingTbody.length && danglingThead.length) { + dom["a" /* default */].append(wrapperTable, danglingThead[0]); + dom["a" /* default */].append(wrapperTable, this._createTheadOrTboday('tbody')); + table = wrapperTable; + } else if (danglingTbody.length && !danglingThead.length) { + dom["a" /* default */].append(wrapperTable, this._createTheadOrTboday('thead')); + dom["a" /* default */].append(wrapperTable, danglingTbody[0]); + table = wrapperTable; + } else if (danglingTbody.length && danglingThead.length) { + dom["a" /* default */].append(wrapperTable, danglingThead[0]); + dom["a" /* default */].append(wrapperTable, danglingTbody[0]); + table = wrapperTable; + } + + return table; + } + /** + * Whether pasting element is table element + * @param {string} pastingNodeName Pasting node name + * @returns {boolean} + */ + ; + + _proto.isTableOrSubTableElement = function isTableOrSubTableElement(pastingNodeName) { + return pastingNodeName === 'TABLE' || pastingNodeName === 'TBODY' || pastingNodeName === 'THEAD' || pastingNodeName === 'TR' || pastingNodeName === 'TD'; + }; + + _proto._createTheadOrTboday = function _createTheadOrTboday(type) { + var theadOrTbody = document.createElement(type); + var tr = document.createElement('tr'); + theadOrTbody.appendChild(tr); + return theadOrTbody; + } + /** + * Stuff table cells into incomplete rows + * @param {HTMLElement} trs HTMLElement wrapped TRs + * @param {number} maximumCellLength maximum cell length of table + * @private + */ + ; + + _proto._stuffTableCellsIntoIncompleteRow = function _stuffTableCellsIntoIncompleteRow(trs, maximumCellLength) { + toArray_default()(trs).forEach(function (row) { + var tableCells = row.querySelectorAll('th,td'); + var parentNodeName = dom["a" /* default */].getNodeName(row.parentNode); + var cellTagName = parentNodeName === 'THEAD' ? 'th' : 'td'; + + for (var cellLength = tableCells.length; cellLength < maximumCellLength; cellLength += 1) { + dom["a" /* default */].append(row, tableCellGenerator(1, cellTagName)); + } + }); + } + /** + * Prepare to table cell stuffing + * @param {HTMLElement} trs wrapped TRs + * @returns {{maximumCellLength: *, needTableCellStuffingAid: boolean}} + */ + ; + + _proto.prepareToTableCellStuffing = function prepareToTableCellStuffing(trs) { + var maximumCellLength = trs[0].querySelectorAll('th,td').length; + var needTableCellStuffingAid = false; + toArray_default()(trs).forEach(function (row) { + var cellCount = row.querySelectorAll('th,td').length; + + if (maximumCellLength !== cellCount) { + needTableCellStuffingAid = true; + + if (maximumCellLength < cellCount) { + maximumCellLength = cellCount; + } + } + }); + return { + maximumCellLength: maximumCellLength, + needTableCellStuffingAid: needTableCellStuffingAid + }; + } + /** + * Add TBODY or THEAD if need + * @param {HTMLElement} table - Table HTMLElement element + * @private + */ + ; + + _proto._addTbodyOrTheadIfNeed = function _addTbodyOrTheadIfNeed(table) { + var isTheadNotExists = !table.querySelector('thead'); + var isTbodyNotExists = !table.querySelector('tbody'); + + if (isTheadNotExists) { + dom["a" /* default */].prepend(table, ''); + } else if (isTbodyNotExists) { + dom["a" /* default */].append(table, ''); + } + } + /** + * Append table cells + * @param {HTMLElement} table Table element + */ + ; + + _proto.tableCellAppendAidForTableElement = function tableCellAppendAidForTableElement(table) { + this._addTbodyOrTheadIfNeed(table); + + this._addTrIntoContainerIfNeed(table); + + var trs = table.querySelectorAll('tr'); + var tableAidInformation = this.prepareToTableCellStuffing(trs); + var maximumCellLength = tableAidInformation.maximumCellLength, + needTableCellStuffingAid = tableAidInformation.needTableCellStuffingAid; + + if (needTableCellStuffingAid) { + this._stuffTableCellsIntoIncompleteRow(trs, maximumCellLength); + } + } + /** + * Generate THEAD and append TDs with same amount of given TBODY + * @param {HTMLElement} node TR element + * @returns {{thead: HTMLElement, tbody: HTMLElement}} + * @private + */ + ; + + _proto._generateTheadAndTbodyFromTbody = function _generateTheadAndTbodyFromTbody(node) { + var tr = document.createElement('tr'); + var thead = document.createElement('thead'); + dom["a" /* default */].append(tr, tableCellGenerator(node.querySelector('tr > td').length, 'th')); + dom["a" /* default */].append(thead, tr); + return { + thead: thead, + tbody: node + }; + } + /** + * Generate TBODY and append TDs with same amount of given THEAD + * @param {HTMLElement} node TR element + * @returns {{thead: HTMLElement, tbody: HTMLElement}} + * @private + */ + ; + + _proto._generateTheadAndTbodyFromThead = function _generateTheadAndTbodyFromThead(node) { + var tr = document.createElement('tr'); + var tbody = document.createElement('tbody'); + dom["a" /* default */].append(tr, tableCellGenerator(node.querySelectorAll('th').length, 'td')); + dom["a" /* default */].append(tbody, tr); + return { + thead: node, + tbody: tbody + }; + } + /** + * Generate THEAD and TBODY and append given TR within + * @param {HTMLElement} node TR element + * @returns {{thead: HTMLElement, tbody: HTMLElement}} + * @private + */ + ; + + _proto._generateTheadAndTbodyFromTr = function _generateTheadAndTbodyFromTr(node) { + var thead = document.createElement('thead'); + var tbody = document.createElement('tbody'); + var theadRow, tbodyRow; + + if (node.children[0].tagName === 'TH') { + theadRow = node; + tbodyRow = dom["a" /* default */].createElementWith("" + tableCellGenerator(node.querySelectorAll('th').length, 'td') + ""); + } else { + theadRow = dom["a" /* default */].createElementWith("" + tableCellGenerator(node.querySelectorAll('td').length, 'th') + ""); + tbodyRow = node; + } + + dom["a" /* default */].append(thead, theadRow); + dom["a" /* default */].append(tbody, tbodyRow); + return { + thead: thead, + tbody: tbody + }; + } + /** + * Complete passed table + * @param {HTMLElement} node - Table inner element + * @private + */ + ; + + _proto._completeIncompleteTable = function _completeIncompleteTable(node) { + var nodeName = node.tagName; + var table, completedTableContents; + + if (nodeName === 'TABLE') { + table = node; + } else { + table = document.createElement('table'); + node.parentNode.insertBefore(table, node.nextSibling); + + if (nodeName === 'TBODY') { + completedTableContents = this._generateTheadAndTbodyFromTbody(node); + } else if (nodeName === 'THEAD') { + completedTableContents = this._generateTheadAndTbodyFromThead(node); + } else if (nodeName === 'TR') { + completedTableContents = this._generateTheadAndTbodyFromTr(node); + } + + table.appendChild(completedTableContents.thead); + table.appendChild(completedTableContents.tbody); + } + + this._removeEmptyRows(table); + + this.tableCellAppendAidForTableElement(table); + }; + + _proto._removeEmptyRows = function _removeEmptyRows(table) { + dom["a" /* default */].findAll(table, 'tr').forEach(function (tr) { + if (!tr.cells.length) { + tr.parentNode.removeChild(tr); + } + }); + } + /** + * Whole editor body searching incomplete table completion + * @private + */ + ; + + _proto._completeTableIfNeed = function _completeTableIfNeed() { + var _this4 = this; + + var body = this.wwe.getEditor().getBody(); + toArray_default()(body.children).forEach(function (node) { + if (!_this4.isTableOrSubTableElement(node.nodeName)) { + return; + } + + if (node.nodeName === 'TABLE' && !node.querySelector('tbody')) { + dom["a" /* default */].remove(node); + } else { + _this4._completeIncompleteTable(node); + } + }); + } + /** + * Reset _lastCellNode to null + */ + ; + + _proto.resetLastCellNode = function resetLastCellNode() { + this._lastCellNode = null; + } + /** + * Set _lastCellNode to given node + * @param {HTMLElement} node Table cell + */ + ; + + _proto.setLastCellNode = function setLastCellNode(node) { + this._lastCellNode = node; + } + /** + * Return whether only modifier key pressed or not + * @param {string} keymap Pressed keymap string + * @returns {boolean} + * @private + */ + ; + + _proto._isModifierKey = function _isModifierKey(keymap) { + return /((META|SHIFT|ALT|CONTROL)\+?)/g.test(keymap); + } + /** + * Return whether modifier keys pressed or not + * @param {object} ev keyboard event object + * @returns {boolean} + * @private + */ + ; + + _proto._isModifierKeyPushed = function _isModifierKeyPushed(ev) { + return ev.metaKey || ev.ctrlKey || ev.altKey || ev.shiftKey; + } + /** + * Add one row into empty TBODY + * @param {HTMLElement} table Currently processing table + * @private + */ + ; + + _proto._addTrIntoContainerIfNeed = function _addTrIntoContainerIfNeed(table) { + toArray_default()(table.children).forEach(function (container) { + var hasNoRows = container.querySelectorAll('tr').length === 0; + + if (hasNoRows) { + dom["a" /* default */].append(container, ''); + } + }); + }; + + _proto._expandTableIfNeed = function _expandTableIfNeed(fragment) { + var range = this.wwe.getEditor().getSelection().cloneRange(); + + var _domUtils$parents = dom["a" /* default */].parents(range.startContainer, 'table'), + table = _domUtils$parents[0]; + + var difference = this._getColumnAndRowDifference(fragment, range); + + if (difference.column < 0) { + this._appendCellForAllRow(table, difference.column); + } + + if (difference.row < 0) { + this._appendRow(table, difference.row); + } + }; + + _proto._getColumnAndRowDifference = function _getColumnAndRowDifference(fragment, range) { + var tableData = this._getTableDataFromTable(fragment); + + var rowLength = tableData.length; + var columnLength = tableData[0].length; + var currentCell = dom["a" /* default */].closest(range.startContainer, 'th,td'); + var currentRow = currentCell.parentNode; + var currentColumnIndex = dom["a" /* default */].getNodeOffsetOfParent(currentCell); + var currentRowIndex = dom["a" /* default */].getNodeOffsetOfParent(currentCell.parentNode); + + var _domUtils$parents2 = dom["a" /* default */].parents(currentRow, 'table'), + table = _domUtils$parents2[0]; + + var tableColumnLength = table.querySelector('tr').children.length; + var tableRowLength = table.querySelectorAll('tr').length; + var isInTbody = !!dom["a" /* default */].parents(currentRow, 'tbody').length; + + if (isInTbody) { + currentRowIndex += 1; + } + + return { + row: tableRowLength - (currentRowIndex + rowLength), + column: tableColumnLength - (currentColumnIndex + columnLength) + }; + }; + + _proto._appendCellForAllRow = function _appendCellForAllRow(table, columnDifference) { + var brString = isIE10 ? '' : '
    '; + dom["a" /* default */].findAll(table, 'tr').forEach(function (row, i) { + var tagName; + + for (var index = columnDifference; index < 0; index += 1) { + if (i === 0) { + tagName = 'th'; + } else { + tagName = 'td'; + } + + dom["a" /* default */].append(row, "<" + tagName + ">" + brString + ""); + } + }); + }; + + _proto._appendRow = function _appendRow(table, rowDifference) { + var trs = table.querySelectorAll('tr'); + var newRow = trs[trs.length - 1].cloneNode(true); + var brHTMLSting = isIE10 ? '' : '
    '; + dom["a" /* default */].findAll(newRow, 'td').forEach(function (td) { + td.innerHTML = brHTMLSting; + }); + + for (; rowDifference < 0; rowDifference += 1) { + dom["a" /* default */].append(table.querySelector('tbody'), newRow.cloneNode(true)); + } + } + /** + * Change selection to sibling cell + * @param {HTMLElement} currentCell current TD or TH + * @param {Range} range Range object + * @param {string} direction 'next' or 'previous' + * @param {string} scale 'row' or 'cell' + * @private + */ + ; + + _proto._changeSelectionToTargetCell = function _changeSelectionToTargetCell(currentCell, range, direction, scale) { + var isNext = direction === 'next'; + var isRow = scale === 'row'; + var target; + + if (isRow) { + target = dom["a" /* default */].getSiblingRowCellByDirection(currentCell, direction, false); + } else { + target = dom["a" /* default */].getTableCellByDirection(currentCell, direction); + + if (!target) { + target = dom["a" /* default */].getSiblingRowCellByDirection(currentCell, direction, true); + } + } + + if (target) { + if (isRow && !isNext) { + this._moveToCursorEndOfCell(target, range); + } else { + range.setStart(target, 0); + } + + range.collapse(true); + } else { + var _domUtils$parents3 = dom["a" /* default */].parents(currentCell, 'table'); + + target = _domUtils$parents3[0]; + + if (isNext) { + range.setStart(target.nextElementSibling, 0); + } else if (target.previousElementSibling && target.previousElementSibling.nodeName !== 'TABLE') { + range.setStart(target.previousElementSibling, 1); + } else { + range.setStartBefore(target); + } + + range.collapse(true); + } + }; + + _proto._moveToCursorEndOfCell = function _moveToCursorEndOfCell(cell, range) { + var lastListItem; + + if (dom["a" /* default */].isListNode(cell.lastChild)) { + lastListItem = dom["a" /* default */].getLastNodeBy(cell.lastChild, function (lastNode) { + return lastNode.nodeName !== 'LI' || lastNode.nextSibling !== null; + }); + } + + var lastText = dom["a" /* default */].getLastNodeBy(lastListItem || cell, function (node) { + return !dom["a" /* default */].isTextNode(node); + }); + var lastNode = lastText || lastListItem || cell; + var offset = lastText ? lastText.length : lastNode.childNodes.length - 1; + range.setStart(lastNode, offset); + } + /** + * Move cursor to given direction by interval formatter + * @param {string} direction 'next' or 'previous' + * @param {string} interval 'row' or 'cell' + * @param {object} [ev] Event object + * @returns {boolean | null} + * @private + */ + ; + + _proto._moveCursorTo = function _moveCursorTo(direction, interval, ev) { + var sq = this.wwe.getEditor(); + var range = sq.getSelection().cloneRange(); + var currentCell = dom["a" /* default */].closest(range.startContainer, 'td,th'); + var isNeedNext; + + if (range.collapsed && this.wwe.isInTable(range) && currentCell) { + if (interval === 'row' && !this._isMovedCursorToRow(range, direction)) { + return isNeedNext; + } + + if ((direction === 'previous' || interval === 'row') && !isUndefined_default()(ev)) { + ev.preventDefault(); + } + + this._changeSelectionToTargetCell(currentCell, range, direction, interval); + + sq.setSelection(range); + isNeedNext = false; + } + + return isNeedNext; + }; + + _proto._isMovedCursorToRow = function _isMovedCursorToRow(range, direction) { + var startContainer = range.startContainer; + + if (this._isInList(startContainer)) { + return this._isMovedCursorFromListToRow(startContainer, direction); + } + + return this._isMovedCursorFromTextToRow(range, direction); + }; + + _proto._isMovedCursorFromListToRow = function _isMovedCursorFromListToRow(startContainer, direction) { + var directionKey = direction + "Sibling"; + + var listItem = this._findListItem(startContainer); + + var parentOfListItem = dom["a" /* default */].getParentNodeBy(listItem, function (parentNode, currentNode) { + var firstOrLastItem = currentNode[directionKey] === null && parentNode[directionKey] === null; + return !dom["a" /* default */].isCellNode(parentNode) && firstOrLastItem; + }); + var firstOrLastList = dom["a" /* default */].isListNode(parentOfListItem) && parentOfListItem[directionKey] === null; + return dom["a" /* default */].isCellNode(parentOfListItem.parentNode) && firstOrLastList; + }; + + _proto._isMovedCursorFromTextToRow = function _isMovedCursorFromTextToRow(range, direction) { + var startContainer = range.startContainer, + startOffset = range.startOffset; + var text = dom["a" /* default */].isCellNode(startContainer) ? startContainer.childNodes[startOffset] : startContainer; + var parentOfStyledText = dom["a" /* default */].getParentNodeBy(text, function (parentNode) { + return !dom["a" /* default */].isCellNode(parentNode) && !dom["a" /* default */].isTextNode(parentNode); + }); + var foundSiblingNode = dom["a" /* default */].getSiblingNodeBy(parentOfStyledText, direction, function (siblingNode) { + return siblingNode !== null && siblingNode.nodeName !== 'BR'; + }); + return foundSiblingNode && foundSiblingNode[direction + "Sibling"] === null; + } + /** + * Remove contents and change selection if need + * @param {Range} range - Range object + * @param {string} keymap - keymap + * @param {object} ev - Event object + * @returns {boolean} - true if contents has been removed + * @private + */ + ; + + _proto._removeContentsAndChangeSelectionIfNeed = function _removeContentsAndChangeSelectionIfNeed(range, keymap, ev) { + var isTextInput = keymap.length <= 1; + var isDeleteOperation = keymap === 'BACK_SPACE' || keymap === 'DELETE'; + var selectedCells = this.wwe.componentManager.getManager('tableSelection').getSelectedCells(); + var firstSelectedCell = selectedCells[0]; + var processed = false; + + if ((isTextInput || isDeleteOperation) && !this._isModifierKeyPushed(ev) && selectedCells.length) { + if (isDeleteOperation) { + this._recordUndoStateIfNeed(range); + } + + this._removeTableContents(selectedCells); + + this._lastCellNode = firstSelectedCell; + range.setStart(firstSelectedCell, 0); + range.collapse(true); + this.wwe.getEditor().setSelection(range); + processed = true; + } + + return processed; + } + /** + * Return new table ID class name string + * @returns {string} + */ + ; + + _proto.getTableIDClassName = function getTableIDClassName() { + var tableClassName = TABLE_CLASS_PREFIX + this.tableID; + this.tableID += 1; + return tableClassName; + } + /** + * Destroy. + */ + ; + + _proto.destroy = function destroy() { + var _this5 = this; + + this.eventManager.removeEventHandler('wysiwygRangeChangeAfter.table'); + this.eventManager.removeEventHandler('wysiwygSetValueAfter.table'); + this.eventManager.removeEventHandler('wysiwygProcessHTMLText.table'); + this.eventManager.removeEventHandler('cut.table'); + this.eventManager.removeEventHandler('copyBefore.table'); + forEachOwnProperties_default()(this.keyEventHandlers, function (handler, key) { + return _this5.wwe.removeKeyEventHandler(key, handler); + }); + }; + + return WwTableManager; +}(); +/** + * Generate table cell HTML text + * @param {number} amount Amount of cells + * @param {string} tagName Tag name of cell 'td' or 'th' + * @private + * @returns {string} + */ + + +function tableCellGenerator(amount, tagName) { + var brHTMLString = '
    '; + var cellString = "<" + tagName + ">" + brHTMLString + ""; + var tdString = ''; + + for (var i = 0; i < amount; i += 1) { + tdString = tdString + cellString; + } + + return tdString; +} + +/* harmony default export */ var wwTableManager = (wwTableManager_WwTableManager); +// CONCATENATED MODULE: ./src/js/wwTableSelectionManager.js +/** + * @fileoverview Implements wysiwyg table selection manager + * @author NHN FE Development Lab + */ + + + + + +var wwTableSelectionManager_TABLE_CELL_SELECTED_CLASS_NAME = 'te-cell-selected'; +/** + * Class WwTableSelectionManager + * @param {WysiwygEditor} wwe - WysiwygEditor instance + * @ignore + */ + +var wwTableSelectionManager_WwTableSelectionManager = /*#__PURE__*/function () { + function WwTableSelectionManager(wwe) { + this.wwe = wwe; + this.eventManager = wwe.eventManager; + /** + * Name property + * @type {string} + */ + + this.name = 'tableSelection'; + + this._init(); + } + /** + * Initialize + * @private + */ + + + var _proto = WwTableSelectionManager.prototype; + + _proto._init = function _init() { + this._initEvent(); // For disable firefox's table tool UI and table resize handler + + + if (browser_default.a.firefox) { + document.execCommand('enableObjectResizing', false, 'false'); + document.execCommand('enableInlineTableEditing', false, 'false'); + } + } + /** + * Initialize event + * @private + */ + ; + + _proto._initEvent = function _initEvent() { + var _this = this; + + var selectionStart, selectionEnd, validSelectionEnd; + /** + * Start table selection timer + * @type {object} + * @private + */ + + this._tableSelectionTimer = null; + /** + * Remove selection timer for Firefox table selection + * @type {object} + * @private + */ + + this._removeSelectionTimer = null; + /** + * Boolean value for whether selection started + * @type {boolean} + * @private + */ + + this._isSelectionStarted = false; + + var onMouseover = function onMouseover(ev) { + selectionEnd = dom["a" /* default */].closest(ev.data.target, '[contenteditable=true] td,th'); + + var range = _this.wwe.getEditor().getSelection(); + + var isEndsInTable = dom["a" /* default */].parents(selectionEnd, '[contenteditable=true] table'); + var isSameCell = selectionStart === selectionEnd; + var isTextSelect = _this._isTextSelect(range, isSameCell) && !hasClass_default()(selectionStart, wwTableSelectionManager_TABLE_CELL_SELECTED_CLASS_NAME); + + if (_this._isSelectionStarted && isEndsInTable && !isTextSelect) { + window.getSelection().removeAllRanges(); // For disable firefox's native table cell selection + + if (browser_default.a.firefox && !_this._removeSelectionTimer) { + _this._removeSelectionTimer = setInterval(function () { + window.getSelection().removeAllRanges(); + }, 10); + } + + if (selectionStart && selectionEnd) { + _this.highlightTableCellsBy(selectionStart, selectionEnd); + + validSelectionEnd = selectionEnd; + } + } + }; + + var finishSelection = function finishSelection() { + if (_this._isSelectionStarted) { + _this._isSelectionStarted = false; + + _this.eventManager.removeEventHandler('mouseover.tableSelection'); + + _this.eventManager.removeEventHandler('mouseup.tableSelection'); + } + }; + + var onMouseup = function onMouseup(ev) { + selectionEnd = dom["a" /* default */].closest(ev.data.target, '[contenteditable=true] td,th'); + + var range = _this.wwe.getEditor().getSelection(); + + var isSameCell = selectionStart === selectionEnd; + var isTextSelect = _this._isTextSelect(range, isSameCell) && !hasClass_default()(selectionStart, wwTableSelectionManager_TABLE_CELL_SELECTED_CLASS_NAME); + + _this._clearTableSelectionTimerIfNeed(); + + if (_this._isSelectionStarted) { + if (isTextSelect || _this._isListSelect(range)) { + _this.removeClassAttrbuteFromAllCellsIfNeed(); + } else { + _this.wwe.componentManager.getManager('table').resetLastCellNode(); + + selectionEnd = selectionEnd || validSelectionEnd; + range = _this.wwe.getEditor().getSelection(); + range.setStart(selectionEnd, 0); // IE wont fire copy/cut event if there is no selected range. + // trick IE to fire the event + + if (browser_default.a.msie) { + range.setEnd(selectionEnd, 1); + } else { + range.setEnd(selectionEnd, 0); + range.collapse(false); + } + + _this.wwe.getEditor().setSelection(range); + } + + if (_this.onDragEnd) { + _this.onDragEnd(); + } + } + + finishSelection(); + }; + + var onMousedown = function onMousedown(ev) { + var MOUSE_RIGHT_BUTTON = 2; + selectionStart = dom["a" /* default */].closest(ev.data.target, '[contenteditable=true] td,th'); + var isSelectedCell = !!selectionStart && hasClass_default()(selectionStart, wwTableSelectionManager_TABLE_CELL_SELECTED_CLASS_NAME); + selectionEnd = null; + + if (!isSelectedCell || isSelectedCell && ev.data.button !== MOUSE_RIGHT_BUTTON) { + _this.removeClassAttrbuteFromAllCellsIfNeed(); + + if (selectionStart) { + _this.setTableSelectionTimerIfNeed(selectionStart); + + _this.eventManager.listen('mouseover.tableSelection', onMouseover); + + _this.eventManager.listen('mouseup.tableSelection', onMouseup); + + if (_this.onDragStart) { + _this.onDragStart(selectionStart); + } + } + } else if (ev.data.button === MOUSE_RIGHT_BUTTON) { + finishSelection(); + } + }; + + this.eventManager.listen('mousedown.tableSelection', onMousedown); + this.eventManager.listen('copyBefore.tableSelection', finishSelection); + this.eventManager.listen('pasteBefore.tableSelection', finishSelection); + } + /** + * Return whether single cell text selection or not + * @param {Range} range Range object + * @param {boolean} isSameCell Boolean value for same cell selection + * @returns {boolean} + * @private + */ + ; + + _proto._isTextSelect = function _isTextSelect(range, isSameCell) { + return /TD|TH|TEXT/i.test(range.commonAncestorContainer.nodeName) && isSameCell; + } + /** + * Return whether list selection or not + * @param {Range} range Range object + * @returns {boolean} + * @private + */ + ; + + _proto._isListSelect = function _isListSelect(range) { + return /UL|OL|LI/i.test(range.commonAncestorContainer.nodeName); + } + /** + * Set setTimeout and setInterval timer execution if table selecting situation + * @param {HTMLElement} selectionStart Start element + */ + ; + + _proto.setTableSelectionTimerIfNeed = function setTableSelectionTimerIfNeed(selectionStart) { + var isTableSelecting = dom["a" /* default */].parents(selectionStart, '[contenteditable=true] table').length; + + if (isTableSelecting) { + this._isSelectionStarted = true; + } + } + /** + * Clear setTimeout and setInterval timer execution + * @private + */ + ; + + _proto._clearTableSelectionTimerIfNeed = function _clearTableSelectionTimerIfNeed() { + clearTimeout(this._tableSelectionTimer); // For disable firefox's native table selection + + if (browser_default.a.firefox && this._removeSelectionTimer) { + clearTimeout(this._removeSelectionTimer); + this._removeSelectionTimer = null; + } + } + /** + * Re arrange selection when table does not include both start and end selection element + * @param {HTMLElement} selectionStart Start element of selection + * @param {HTMLElement} selectionEnd End element of selection + * @returns {{startContainer: HTMLElement, endContainer: HTMLElement}} + * @private + */ + ; + + _proto._reArrangeSelectionIfneed = function _reArrangeSelectionIfneed(selectionStart, selectionEnd) { + var isRangeStartInTable = dom["a" /* default */].parents(selectionStart, '[contenteditable=true] table').length; + var isRangeEndInTable = dom["a" /* default */].parents(selectionEnd, '[contenteditable=true] table').length; + var isStartRangeOut = isRangeEndInTable && !isRangeStartInTable; + var isEndRangeOut = !isRangeEndInTable && isRangeStartInTable; + var table; + + if (isStartRangeOut) { + var _domUtils$parents = dom["a" /* default */].parents(selectionEnd, '[contenteditable=true] table'); + + table = _domUtils$parents[0]; + + var _table$querySelectorA = table.querySelectorAll('th'); + + selectionStart = _table$querySelectorA[0]; + } else if (isEndRangeOut) { + var _domUtils$parents2 = dom["a" /* default */].parents(selectionStart, '[contenteditable=true] table'); + + table = _domUtils$parents2[0]; + var tds = table.querySelectorAll('td'); + selectionEnd = tds[tds.length - 1]; + } + + return { + startContainer: selectionStart, + endContainer: selectionEnd + }; + } + /** + * Apply select direction to editor + * @param {{startContainer: HTMLElement, endContainer: HTMLElement}} selectionInformation + * Selection start and end element + * @param {Range} range Range object + * @returns {Range} + * @private + */ + ; + + _proto._applySelectionDirection = function _applySelectionDirection(selectionInformation, range) { + var nodeOffsetOfParent = dom["a" /* default */].getNodeOffsetOfParent; + var selectionStart = selectionInformation.startContainer; + var selectionEnd = selectionInformation.endContainer; + var rowDirection = nodeOffsetOfParent(dom["a" /* default */].closest(selectionStart, '[contenteditable=true] tr')) - nodeOffsetOfParent(dom["a" /* default */].closest(selectionEnd, '[contenteditable=true] tr')); + var cellDirection = nodeOffsetOfParent(selectionStart) - nodeOffsetOfParent(selectionEnd); + var isSameRow = rowDirection === 0; + var isRowIncreases = rowDirection < 0; + var isColumnIncreases = cellDirection > 0; + + if (isSameRow) { + if (isColumnIncreases) { + range.setStart(selectionEnd, 0); + range.setEnd(selectionStart, 1); + } else { + range.setStart(selectionStart, 0); + range.setEnd(selectionEnd, 1); + } + } else if (isRowIncreases) { + range.setStart(selectionStart, 0); + range.setEnd(selectionEnd, 1); + } else { + range.setStart(selectionEnd, 0); + range.setEnd(selectionStart, 1); + } + + return range; + } + /** + * Get selection coordinate by current selection + * @param {HTMLElement} selectionStart start element + * @param {HTMLElement} selectionEnd end element + * @returns {{from: {row: number, cell: number}, to: {row: number, cell: number}}} + */ + ; + + _proto.getSelectionRangeFromTable = function getSelectionRangeFromTable(selectionStart, selectionEnd) { + var nodeOffsetOfParent = dom["a" /* default */].getNodeOffsetOfParent; + var startRowOffset = nodeOffsetOfParent(selectionStart.parentNode); + var endRowOffset = nodeOffsetOfParent(selectionEnd.parentNode); + var startCellOffset = nodeOffsetOfParent(selectionStart); + var endCellOffset = nodeOffsetOfParent(selectionEnd); + var startCellContainer = dom["a" /* default */].getParentUntil(selectionStart, 'TABLE'); + var endCellContainer = dom["a" /* default */].getParentUntil(selectionEnd, 'TABLE'); + var isReversedTheadAndTbodySelect = dom["a" /* default */].getNodeName(startCellContainer) === 'TBODY' && dom["a" /* default */].getNodeName(endCellContainer) === 'THEAD'; + var isTheadAndTbodySelect = startCellContainer !== endCellContainer; + var isBothInTbody = !!dom["a" /* default */].parents(selectionStart, 'tbody').length && !!dom["a" /* default */].parents(selectionEnd, 'tbody').length; + var start = { + row: startRowOffset, + cell: startCellOffset + }; + var end = { + row: endRowOffset, + cell: endCellOffset + }; + var from, to; + + if (isReversedTheadAndTbodySelect) { + start.row += 1; + } else if (isTheadAndTbodySelect) { + end.row += 1; + } else if (isBothInTbody) { + start.row += 1; + end.row += 1; + } + + if (startRowOffset > endRowOffset || startRowOffset === endRowOffset && startCellOffset > endCellOffset) { + from = end; + to = start; + } else { + from = start; + to = end; + } + + return { + from: from, + to: to + }; + } + /** + * Highlight selected table cells + * @param {HTMLElement} selectionStart start element + * @param {HTMLElement} selectionEnd end element + */ + ; + + _proto.highlightTableCellsBy = function highlightTableCellsBy(selectionStart, selectionEnd) { + var trs = dom["a" /* default */].findAll(dom["a" /* default */].parents(selectionStart, '[contenteditable=true] table')[0], 'tr'); + var selection = this.getSelectionRangeFromTable(selectionStart, selectionEnd); + var rowFrom = selection.from.row; + var cellFrom = selection.from.cell; + var rowTo = selection.to.row; + var cellTo = selection.to.cell; + trs.forEach(function (row, rowIndex) { + dom["a" /* default */].findAll(row, 'td,th').forEach(function (cell, cellIndex) { + var isFromRow = rowIndex === rowFrom; + var isToRow = rowIndex === rowTo; + + if (isFromRow && cellIndex < cellFrom || isToRow && cellIndex > cellTo || rowIndex < rowFrom || rowIndex > rowTo) { + removeClass_default()(cell, wwTableSelectionManager_TABLE_CELL_SELECTED_CLASS_NAME); + } else { + addClass_default()(cell, wwTableSelectionManager_TABLE_CELL_SELECTED_CLASS_NAME); + } + }); + }); + } + /** + * Remove '.te-cell-selected' class from all of table Cell + */ + ; + + _proto.removeClassAttrbuteFromAllCellsIfNeed = function removeClassAttrbuteFromAllCellsIfNeed() { + var cells = dom["a" /* default */].findAll(this.wwe.getBody(), "td." + wwTableSelectionManager_TABLE_CELL_SELECTED_CLASS_NAME + ",th." + wwTableSelectionManager_TABLE_CELL_SELECTED_CLASS_NAME); + cells.forEach(function (node) { + removeClass_default()(node, wwTableSelectionManager_TABLE_CELL_SELECTED_CLASS_NAME); + + if (!node.getAttribute('class')) { + node.removeAttribute('class'); + } + }); + } + /** + * gets selected cells + * @returns {HTMLElement} selected cells + */ + ; + + _proto.getSelectedCells = function getSelectedCells() { + return this.wwe.getBody().querySelectorAll("." + wwTableSelectionManager_TABLE_CELL_SELECTED_CLASS_NAME); + } + /** + * Create selection by selected cells and collapse that selection to end + */ + ; + + _proto.createRangeBySelectedCells = function createRangeBySelectedCells() { + var sq = this.wwe.getEditor(); + var range = sq.getSelection().cloneRange(); + var selectedCells = this.getSelectedCells(); + var firstSelectedCell = selectedCells[0]; + var lastSelectedCell = selectedCells[selectedCells.length - 1]; + + if (selectedCells.length && this.wwe.isInTable(range)) { + range.setStart(firstSelectedCell, 0); + range.setEnd(lastSelectedCell, lastSelectedCell.childNodes.length); + sq.setSelection(range); + } + } + /** + * Style to selected cells. + * @param {function} onStyle - function for styling + * @param {Object} [options] - options to be passed into onStyle + */ + ; + + _proto.styleToSelectedCells = function styleToSelectedCells(onStyle, options) { + this.createRangeBySelectedCells(); + onStyle(this.wwe.getEditor(), options); + } + /** + * Destroy. + */ + ; + + _proto.destroy = function destroy() { + this.eventManager.removeEventHandler('mousedown.tableSelection'); + this.eventManager.removeEventHandler('mouseover.tableSelection'); + this.eventManager.removeEventHandler('mouseup.tableSelection'); + this.eventManager.removeEventHandler('copyBefore.tableSelection'); + this.eventManager.removeEventHandler('pasteBefore.tableSelection'); + }; + + return WwTableSelectionManager; +}(); + +/* harmony default export */ var wwTableSelectionManager = (wwTableSelectionManager_WwTableSelectionManager); +// CONCATENATED MODULE: ./src/js/wwHrManager.js +/** + * @fileoverview Implements wysiwyg hr manager + * @author NHN FE Development Lab + */ + +/** + * Class WwHrManager + * @param {WysiwygEditor} wwe - WysiwygEditor instance + * @ignore + */ + +var wwHrManager_WwHrManager = /*#__PURE__*/function () { + function WwHrManager(wwe) { + this.wwe = wwe; + this.eventManager = wwe.eventManager; + /** + * Name property + * @type {string} + */ + + this.name = 'hr'; + + this._init(); + } + /** + * Initialize + * @private + */ + + + var _proto = WwHrManager.prototype; + + _proto._init = function _init() { + this._initEvent(); + } + /** + * Initialize eventmanager event + * @private + */ + ; + + _proto._initEvent = function _initEvent() { + var _this = this; + + this.eventManager.listen('wysiwygSetValueAfter', function () { + _this._insertEmptyLineIfNeed(); + + _this._changeHRForWysiwyg(); + }); + } + /** + * If
    is frist or last child of root, insert empty line before or after HR + * @private + */ + ; + + _proto._insertEmptyLineIfNeed = function _insertEmptyLineIfNeed() { + var editorContentBody = this.wwe.getBody(); + var firstChild = editorContentBody.firstChild, + lastChild = editorContentBody.lastChild; + + if (firstChild && firstChild.nodeName === 'HR') { + editorContentBody.insertBefore(dom["a" /* default */].createEmptyLine(), firstChild); + } else if (lastChild && lastChild.nodeName === 'HR') { + editorContentBody.appendChild(dom["a" /* default */].createEmptyLine()); + } + } + /** + *
    is set contenteditable to false with wrapping div like below. + *

    + * @private + */ + ; + + _proto._changeHRForWysiwyg = function _changeHRForWysiwyg() { + var editorContentBody = this.wwe.getBody(); + dom["a" /* default */].findAll(editorContentBody, 'hr').forEach(function (hrNode) { + var parentNode = hrNode.parentNode; + parentNode.replaceChild(dom["a" /* default */].createHorizontalRule(), hrNode); + }); + }; + + return WwHrManager; +}(); + +/* harmony default export */ var wwHrManager = (wwHrManager_WwHrManager); +// CONCATENATED MODULE: ./src/js/wwPManager.js +/** + * @fileoverview Implements wysiwyg p tag manager + * @author NHN FE Development Lab + */ + + +/** + * Class WwPManager + * @param {WysiwygEditor} wwe - wysiwygEditor instance + * @ignore + */ + +var wwPManager_WwPManager = /*#__PURE__*/function () { + function WwPManager(wwe) { + this.wwe = wwe; + this.eventManager = wwe.eventManager; + /** + * Name property + * @type {string} + */ + + this.name = 'p'; + + this._initEvent(); + } + /** + * Initialize event + * @private + */ + + + var _proto = WwPManager.prototype; + + _proto._initEvent = function _initEvent() { + var _this = this; + + this.eventManager.listen('wysiwygSetValueBefore', function (html) { + return _this._splitPtagContentLines(html); + }); + this.eventManager.listen('wysiwygSetValueAfter', function () { + _this._ensurePtagContentWrappedWithDiv(); + + _this._unwrapPtags(); + }); + } + /** + * Split multiple line content of p tags + * @param {string} html html text + * @returns {string} result + * @private + */ + ; + + _proto._splitPtagContentLines = function _splitPtagContentLines(html) { + if (html) { + var wrapper = dom["a" /* default */].createElementWith("
    " + html + "
    "); + dom["a" /* default */].findAll(wrapper, 'p').forEach(function (para) { + var attributes = para.attributes, + nextElementSibling = para.nextElementSibling; + var content = para.innerHTML; + var lines = content.split(/
    /gi); + var lastIndex = lines.length - 1; + var splitedContent = ''; + splitedContent = lines.map(function (line, index) { + if (index > 0 && index < lastIndex) { + line = line ? line : '
    '; + } + + if (line) { + var block = document.createElement('div'); + Object.keys(attributes).forEach(function (key) { + var _attributes$key = attributes[key], + name = _attributes$key.name, + value = _attributes$key.value; + block.setAttribute(name, value); + }); + block.innerHTML = line; + return block.outerHTML; + } + + return ''; + }); // For paragraph, we add empty line + + if (nextElementSibling && nextElementSibling.nodeName === 'P' || para.getAttribute('contenteditable') === 'false') { + splitedContent.push('

    '); + } + + dom["a" /* default */].replaceWith(para, splitedContent.join('')); + }); + html = wrapper.innerHTML; + } + + return html; + } + /** + * Wrap new line inside P tag to DIV, and additional empty line added within too + * @private + */ + ; + + _proto._ensurePtagContentWrappedWithDiv = function _ensurePtagContentWrappedWithDiv() { + var _this2 = this; + + dom["a" /* default */].findAll(this.wwe.getBody(), 'p').forEach(function (node) { + if (!node.querySelectorAll('div').length) { + dom["a" /* default */].wrapInner(node, 'div'); + } + + if (_this2._findNextParagraph(node, 'p')) { + dom["a" /* default */].append(node, '

    '); + } + }); + } + /** + * Unwrap P tag + * @private + */ + ; + + _proto._unwrapPtags = function _unwrapPtags() { + dom["a" /* default */].findAll(this.wwe.getBody(), 'div').forEach(function (node) { + var parent = node.parentNode; + + if (parent.tagName === 'P') { + dom["a" /* default */].unwrap(parent); + } + }); + }; + + _proto._findNextParagraph = function _findNextParagraph(node, selector) { + var nextElementSibling = node.nextElementSibling; + + if (selector) { + return nextElementSibling && matches_default()(nextElementSibling, selector) ? nextElementSibling : null; + } + + return nextElementSibling; + }; + + return WwPManager; +}(); + +/* harmony default export */ var wwPManager = (wwPManager_WwPManager); +// CONCATENATED MODULE: ./src/js/wwHeadingManager.js +/** + * @fileoverview Implements wysiwyg heading manager + * @author NHN FE Development Lab + */ + + +var wwHeadingManager_FIND_HEADING_RX = /h[\d]/i; +var wwHeadingManager_isIE10 = browser_default.a.msie && browser_default.a.version === 10; +/** + * Class WwHeadingManager + * @param {WysiwygEditor} wwe - WysiwygEditor instance + * @ignore + */ + +var wwHeadingManager_WwHeadingManager = /*#__PURE__*/function () { + function WwHeadingManager(wwe) { + this.wwe = wwe; + this.eventManager = wwe.eventManager; + /** + * Name property + * @type {string} + */ + + this.name = 'heading'; + + this._init(); + } + /** + * Initialize + * @private + */ + + + var _proto = WwHeadingManager.prototype; + + _proto._init = function _init() { + this._initEvent(); + + this._initKeyHandler(); + }; + + _proto._initEvent = function _initEvent() { + var _this = this; + + this.eventManager.listen('wysiwygSetValueAfter', function () { + _this._wrapDefaultBlockToHeadingInner(); + }); + } + /** + * Initialize key event handler + * @private + */ + ; + + _proto._initKeyHandler = function _initKeyHandler() { + var _this2 = this; + + this.wwe.addKeyEventHandler('ENTER', function (ev, range) { + if (_this2.wwe.hasFormatWithRx(wwHeadingManager_FIND_HEADING_RX)) { + _this2._onEnter(ev, range); + + return false; + } + + return true; + }); + this.wwe.addKeyEventHandler('BACK_SPACE', function (ev, range) { + if (_this2.wwe.hasFormatWithRx(wwHeadingManager_FIND_HEADING_RX)) { + _this2._addBrToEmptyBlock(range); + + _this2._removePrevTopNodeIfNeed(ev, range); + + return false; + } + + return true; + }); + } + /** + * Wrap default block to heading inner contents + * @private + */ + ; + + _proto._wrapDefaultBlockToHeadingInner = function _wrapDefaultBlockToHeadingInner() { + var headingTags = dom["a" /* default */].findAll(this.wwe.getBody(), 'h1, h2, h3, h4, h5, h6'); + headingTags.forEach(function (headingTag) { + var exceptedForWrapping = !dom["a" /* default */].children(headingTag, 'div, p').length; + + if (exceptedForWrapping) { + dom["a" /* default */].wrapInner(headingTag, 'div'); + } + }); + } + /** + * Unwrap heading + * @private + */ + ; + + _proto._unwrapHeading = function _unwrapHeading() { + this.wwe.unwrapBlockTag(function (node) { + return wwHeadingManager_FIND_HEADING_RX.test(node); + }); + } + /** + * Enter key handler + * @param {Event} event event object + * @param {Range} range range + * @private + */ + ; + + _proto._onEnter = function _onEnter(event, range) { + var _this3 = this; + + if (range.startOffset > 0) { + // I hate this but there's no way + this.wwe.defer(function (wwe) { + _this3._unwrapHeading(); + + wwe.getEditor().removeLastUndoStack(); + }); + } else { + event.preventDefault(); + + this._insertEmptyBlockToPrevious(range); + } + } + /** + * Insert empty block to previous of passed range + * @param {Range} range range + * @private + */ + ; + + _proto._insertEmptyBlockToPrevious = function _insertEmptyBlockToPrevious(range) { + this.wwe.getEditor().saveUndoState(range); + var element = dom["a" /* default */].createElementWith('

    '); + dom["a" /* default */].insertBefore(element, dom["a" /* default */].getParentUntil(range.startContainer, this.wwe.getBody())); + } + /** + * Remove previous top node if need + * @param {Event} event event object + * @param {Range} range range + * @returns {Boolean} whether needed or not + * @private + */ + ; + + _proto._removePrevTopNodeIfNeed = function _removePrevTopNodeIfNeed(event, range) { + var isHandled = false; + + if (range.collapsed && range.startOffset === 0) { + var startContainer = range.startContainer; + var prevTopNode = dom["a" /* default */].getTopPrevNodeUnder(startContainer, this.wwe.getBody()); + var isPrevTopNodeEmpty = prevTopNode && prevTopNode.textContent.length === 0; + var sq = this.wwe.getEditor(); + + if (startContainer.textContent.length === 0) { + isHandled = this._removeHedingAndChangeSelection(event, range, prevTopNode); + } else if (isPrevTopNodeEmpty) { + event.preventDefault(); + sq.saveUndoState(range); + dom["a" /* default */].remove(prevTopNode); + isHandled = true; + } + } + + return isHandled; + }; + + _proto._getHeadingElement = function _getHeadingElement(element) { + var isHeading = wwHeadingManager_FIND_HEADING_RX.test(dom["a" /* default */].getNodeName(element)); + return isHeading ? element : dom["a" /* default */].parents(element, 'h1,h2,h3,h4,h5,h6')[0]; + }; + + _proto._addBrToEmptyBlock = function _addBrToEmptyBlock(range) { + var collapsed = range.collapsed, + startOffset = range.startOffset, + startContainer = range.startContainer; + + if (collapsed && startOffset === 1) { + var headingElement = this._getHeadingElement(startContainer); + + var brs = dom["a" /* default */].children(headingElement.firstChild, 'br'); + + if (!wwHeadingManager_isIE10 && !brs.length) { + var br = document.createElement('br'); + startContainer.parentNode.appendChild(br); + } + } + } + /** + * Remove heading and change selection + * @param {object} event Event object + * @param {Range} range Range object + * @param {HTMLElement} prevTopNode Previous top node + * @returns {boolean} + * @private + */ + ; + + _proto._removeHedingAndChangeSelection = function _removeHedingAndChangeSelection(event, range, prevTopNode) { + var startContainer = range.startContainer; + var sq = this.wwe.getEditor(); + var body = this.wwe.getBody(); + + var headingElement = this._getHeadingElement(startContainer); + + var targetNode = prevTopNode; + var offset = 1; + + if (!event.defaultPrevented) { + event.preventDefault(); + sq.saveUndoState(range); + } + + dom["a" /* default */].remove(headingElement); + + if (!prevTopNode) { + var _domUtils$children = dom["a" /* default */].children(body, 'div'); + + targetNode = _domUtils$children[0]; + offset = 0; + } + + range.setStart(targetNode, offset); + range.collapse(true); + sq.setSelection(range); + return true; + }; + + return WwHeadingManager; +}(); + +/* harmony default export */ var wwHeadingManager = (wwHeadingManager_WwHeadingManager); +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/type/isTruthy.js +var isTruthy = __webpack_require__(42); +var isTruthy_default = /*#__PURE__*/__webpack_require__.n(isTruthy); + +// CONCATENATED MODULE: ./src/js/wwCodeBlockManager.js +/** + * @fileoverview Implements wysiwyg code block manager + * @author NHN FE Development Lab + */ + + + + + + +var wwCodeBlockManager_isIE10 = browser_default.a.msie && browser_default.a.version === 10; +var wwCodeBlockManager_brString = wwCodeBlockManager_isIE10 ? '' : '
    '; +var tagEntities = { + '&': '&', + '<': '<', + '>': '>' +}; +var FIND_ZWS_RX = /\u200B/g; +var CODEBLOCK_ATTR_NAME = 'data-te-codeblock'; +/** + * Class WwCodeBlockManager + * @param {WysiwygEditor} wwe - wysiwygEditor instance + * @ignore + */ + +var wwCodeBlockManager_WwCodeBlockManager = /*#__PURE__*/function () { + function WwCodeBlockManager(wwe) { + this.wwe = wwe; + this.eventManager = wwe.eventManager; + /** + * Name property + * @type {string} + */ + + this.name = 'codeblock'; + + this._init(); + } + /** + * Initialize + * @private + */ + + + var _proto = WwCodeBlockManager.prototype; + + _proto._init = function _init() { + this._initKeyHandler(); + + this._initEvent(); + } + /** + * Initialize key event handler + * @private + */ + ; + + _proto._initKeyHandler = function _initKeyHandler() { + var _this = this; + + this._keyEventHandlers = { + BACK_SPACE: this._onBackspaceKeyEventHandler.bind(this), + ENTER: function ENTER(ev, range) { + if (!_this.wwe.isInTable(range) && _this.wwe.getEditor().hasFormat('CODE')) { + _this.wwe.defer(function () { + var _this$wwe$getRange = _this.wwe.getRange(), + startContainer = _this$wwe$getRange.startContainer; + + var codeNode = _this._getCodeNode(startContainer); + + if (codeNode && !dom["a" /* default */].getTextLength(codeNode)) { + codeNode.parentNode.removeChild(codeNode); + } + }); + } + } + }; + forEachOwnProperties_default()(this._keyEventHandlers, function (handler, key) { + return _this.wwe.addKeyEventHandler(key, handler); + }); + }; + + _proto._getCodeNode = function _getCodeNode(node) { + var result; + + if (node.nodeName === 'CODE') { + result = node; + } else if (node.parentNode.nodeName === 'CODE') { + result = node.parentNode; + } + + return result; + } + /** + * Initialize eventmanager event + * @private + */ + ; + + _proto._initEvent = function _initEvent() { + var _this2 = this; + + this.eventManager.listen('wysiwygSetValueAfter.codeblock', function () { + _this2.modifyCodeBlockForWysiwyg(); + }); + this.eventManager.listen('wysiwygProcessHTMLText.codeblock', function (html) { + return _this2._changePreToPreCode(html); + }); + } + /** + * Prepare nodes for pasting to code block + * @param {Array.} nodes Node array + * @returns {DocumentFragment} + */ + ; + + _proto.prepareToPasteOnCodeblock = function prepareToPasteOnCodeblock(nodes) { + var frag = this.wwe.getEditor().getDocument().createDocumentFragment(); + var text = this.convertNodesToText(nodes); + text = text.replace(/\n$/, ''); + frag.appendChild(document.createTextNode(text)); + return frag; + } + /** + * Convert nodes to text for pasting to code block + * @param {Array.} nodes Node array + * @returns {string} coverted string + */ + ; + + _proto.convertNodesToText = function convertNodesToText(nodes) { + var str = ''; + var node = nodes.shift(); + + while (isTruthy_default()(node)) { + var _node = node, + childNodes = _node.childNodes; + + if (childNodes && dom["a" /* default */].isBlockNode(node)) { + str += this.convertNodesToText(toArray_default()(node.childNodes)); + } else if (node.nodeName === 'BR') { + str += '\n'; + } else { + str += node.textContent; + } + + node = nodes.shift(); + } + + return str; + } + /** + * Copy content with code block style from code block selection + * @param {HTMLElement} element Copied element + * @param {Range} range Range object + * @returns {HTMLElement} + * @private + */ + ; + + _proto._copyCodeblockTypeFromRangeCodeblock = function _copyCodeblockTypeFromRangeCodeblock(element, range) { + var blockNode = dom["a" /* default */].getParentUntil(range.commonAncestorContainer, this.wwe.getBody()); + + if (dom["a" /* default */].getNodeName(blockNode) === 'PRE') { + var attrs = blockNode.attributes; + forEachOwnProperties_default()(attrs, function (attr) { + element.setAttribute(attr.name, attr.value); + }); + } + + return element; + } + /** + * Change pre tag to pre and code + * @param {string} html HTML string + * @returns {string} + * @private + */ + ; + + _proto._changePreToPreCode = function _changePreToPreCode(html) { + return html.replace(/((.|\n)*?)<\/pre>/g, function (match, codeAttr, code) { + return "
    " + code + "
    "; + }); + } + /** + * Modify Code Block for Wysiwyg + * @param {HTMLElement} node root node to find pre + */ + ; + + _proto.modifyCodeBlockForWysiwyg = function modifyCodeBlockForWysiwyg(node) { + if (!node) { + node = this.wwe.getBody(); + } + + dom["a" /* default */].findAll(node, 'pre').forEach(function (pre) { + var codeTag = pre.querySelector('code'); + var lang, numberOfBackticks; + + if (codeTag) { + lang = codeTag.getAttribute('data-language'); + numberOfBackticks = codeTag.getAttribute('data-backticks'); + } // if this pre can have lines + + + if (pre.children.length > 1) { + toArray_default()(pre.children).forEach(function (childNode) { + if ((childNode.nodeName === 'DIV' || childNode.nodeName === 'P') && !childNode.querySelectorAll('br').length) { + childNode.innerHTML += childNode.innerHTML + "\n"; + } + }); + } + + var brs = pre.querySelectorAll('br'); + + if (brs.length) { + dom["a" /* default */].replaceWith(brs, '\n'); + } + + var resultText = pre.textContent.replace(/\s+$/, ''); + dom["a" /* default */].empty(pre); + pre.innerHTML = resultText ? sanitizeHtmlCode(resultText) : wwCodeBlockManager_brString; + + if (lang) { + pre.setAttribute('data-language', lang); + addClass_default()(pre, "lang-" + lang); + } + + if (numberOfBackticks) { + pre.setAttribute('data-backticks', numberOfBackticks); + } + + pre.setAttribute(CODEBLOCK_ATTR_NAME, ''); + }); + } + /** + * Remove codeblock of first line when press backspace in first line + * @param {Event} ev Event object + * @param {Range} range Range object + * @returns {boolean} + * @private + */ + ; + + _proto._onBackspaceKeyEventHandler = function _onBackspaceKeyEventHandler(ev, range) { + var isNeedNext = true; + var sq = this.wwe.getEditor(); + var container = range.commonAncestorContainer; + + if (this._isCodeBlockFirstLine(range) && !this._isFrontCodeblock(range)) { + this._removeCodeblockFirstLine(container); + + range.collapse(true); + isNeedNext = false; + } else if (range.collapsed && this._isEmptyLine(container) && this._isBetweenSameCodeblocks(container)) { + var previousSibling = container.previousSibling, + nextSibling = container.nextSibling; + var prevTextLength = previousSibling.textContent.length; + sq.saveUndoState(range); + container.parentNode.removeChild(container); + + this._mergeCodeblocks(previousSibling, nextSibling); + + range.setStart(previousSibling.childNodes[0], prevTextLength); + range.collapse(true); + isNeedNext = false; + } + + if (!isNeedNext) { + sq.setSelection(range); + ev.preventDefault(); + } + + return isNeedNext; + } + /** + * Check node is empty line + * @param {Node} node node + * @returns {boolean} + * @private + */ + ; + + _proto._isEmptyLine = function _isEmptyLine(node) { + var nodeName = node.nodeName, + childNodes = node.childNodes; + var isEmpty = wwCodeBlockManager_isIE10 ? node.textContent === '' : childNodes.length === 1 && childNodes[0].nodeName === 'BR'; + return nodeName === 'DIV' && isEmpty; + } + /** + * Check whether node is between same codeblocks + * @param {Node} node Node + * @returns {boolean} + * @private + */ + ; + + _proto._isBetweenSameCodeblocks = function _isBetweenSameCodeblocks(node) { + var previousSibling = node.previousSibling, + nextSibling = node.nextSibling; + return dom["a" /* default */].getNodeName(previousSibling) === 'PRE' && dom["a" /* default */].getNodeName(nextSibling) === 'PRE' && previousSibling.getAttribute('data-language') === nextSibling.getAttribute('data-language'); + }; + + _proto._mergeCodeblocks = function _mergeCodeblocks(frontCodeblock, backCodeblock) { + var postText = backCodeblock.textContent; + frontCodeblock.childNodes[0].textContent += "\n" + postText; + backCodeblock.parentNode.removeChild(backCodeblock); + } + /** + * Check whether range is first line of code block + * @param {Range} range Range object + * @returns {boolean} + * @private + */ + ; + + _proto._isCodeBlockFirstLine = function _isCodeBlockFirstLine(range) { + return this.isInCodeBlock(range) && range.collapsed && range.startOffset === 0; + } + /** + * Check whether front block of range is code block + * @param {Range} range Range object + * @returns {boolean} + * @private + */ + ; + + _proto._isFrontCodeblock = function _isFrontCodeblock(range) { + var block = dom["a" /* default */].getParentUntil(range.startContainer, this.wwe.getEditor().getRoot()); + var previousSibling = block.previousSibling; + return previousSibling && previousSibling.nodeName === 'PRE'; + } + /** + * Remove codeblock first line of codeblock + * @param {Node} node Pre Node + * @private + */ + ; + + _proto._removeCodeblockFirstLine = function _removeCodeblockFirstLine(node) { + var sq = this.wwe.getEditor(); + var preNode = node.nodeName === 'PRE' ? node : node.parentNode; + var codeContent = preNode.textContent.replace(FIND_ZWS_RX, ''); + sq.modifyBlocks(function () { + var newFrag = sq.getDocument().createDocumentFragment(); + var strArray = codeContent.split('\n'); + var firstDiv = document.createElement('div'); + var firstLine = strArray.shift(); + firstDiv.innerHTML = "" + sanitizeHtmlCode(firstLine) + wwCodeBlockManager_brString; + newFrag.appendChild(firstDiv); + + if (strArray.length) { + var newPreNode = preNode.cloneNode(); + newPreNode.textContent = strArray.join('\n'); + newFrag.appendChild(newPreNode); + } + + return newFrag; + }); + } + /** + * Return boolean value of whether current range is in the code block + * @param {Range} range Range object + * @returns {boolean} + */ + ; + + _proto.isInCodeBlock = function isInCodeBlock(range) { + var target; + + if (range.collapsed) { + target = range.startContainer; + } else { + target = range.commonAncestorContainer; + } + + return !!dom["a" /* default */].closest(target, 'pre'); + } + /** + * Destroy + */ + ; + + _proto.destroy = function destroy() { + var _this3 = this; + + this.eventManager.removeEventHandler('wysiwygSetValueAfter.codeblock'); + this.eventManager.removeEventHandler('wysiwygProcessHTMLText.codeblock'); + forEachOwnProperties_default()(this._keyEventHandlers, function (handler, key) { + return _this3.wwe.removeKeyEventHandler(key, handler); + }); + }; + + return WwCodeBlockManager; +}(); +/** + * Sanitize HTML code + * @param {string} code code string + * @returns {string} + * @ignore + */ + + +function sanitizeHtmlCode(code) { + return code ? code.replace(/[<>&]/g, function (tag) { + return tagEntities[tag] || tag; + }) : ''; +} + +/* harmony default export */ var wwCodeBlockManager = (wwCodeBlockManager_WwCodeBlockManager); +// EXTERNAL MODULE: /Users/nhn/project/tui.editor/libs/squire/build/squire.js +var build_squire = __webpack_require__(55); +var squire_default = /*#__PURE__*/__webpack_require__.n(build_squire); + +// CONCATENATED MODULE: ./src/js/squireExt.js +function squireExt_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements squire extension + * @author NHN FE Development Lab + */ + + + + + + +var FIND_BLOCK_TAGNAME_RX = /\b(H[\d]|LI|P|BLOCKQUOTE|TD)\b/; +var isIElt11 = /Trident\/[456]\./.test(navigator.userAgent); +/** + * Class SquireExt + * @params {Squire} ...args + */ + +var squireExt_SquireExt = /*#__PURE__*/function (_Squire) { + squireExt_inheritsLoose(SquireExt, _Squire); + + function SquireExt() { + var _this; + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + _this = _Squire.call.apply(_Squire, [this].concat(args)) || this; + + _this._decorateHandlerToCancelable('copy'); + + _this._decorateHandlerToCancelable(isIElt11 ? 'beforecut' : 'cut'); + + _this._decorateHandlerToCancelable(isIElt11 ? 'beforepaste' : 'paste'); + + _this.getBody = function () { + _this.body = _this.body || _this.getRoot(); + return _this.body; + }; + + return _this; + } + /** + * Decorate squire handler to cancelable cuz sometimes, we dont need squire handler process + * event.preventDefault() will cancel squire and browser default behavior + * event.squirePrevented = true will cancel squire but allow browser default behavior + * @param {string} eventName event name + * @private + */ + + + var _proto = SquireExt.prototype; + + _proto._decorateHandlerToCancelable = function _decorateHandlerToCancelable(eventName) { + var handlers = this._events[eventName]; + + if (handlers.length > 1) { + throw new Error("too many" + eventName + "handlers in squire"); + } + + var handler = handlers[0].bind(this); + + handlers[0] = function (event) { + if (!event.defaultPrevented && !event.squirePrevented) { + handler(event); + } + }; + }; + + _proto.changeBlockFormat = function changeBlockFormat(srcCondition, targetTagName) { + var _this2 = this; + + this.modifyBlocks(function (frag) { + var current, newFrag, newBlock, nextBlock, tagName, lastNodeOfNextBlock, appendChidToNextBlock; // HR is non-block element, so frag don't have it + // make a default block + + if (frag.childNodes.length) { + current = frag.childNodes.item(0); + } else { + current = _this2.createDefaultBlock(); + frag.appendChild(current); + } + + if (srcCondition) { + // find last depth + while (current.firstChild) { + current = current.firstChild; + } + + appendChidToNextBlock = function appendChidToNextBlock(node) { + nextBlock.appendChild(node); + }; // find tag + + + while (current !== frag) { + var _current = current; + tagName = _current.tagName; + + if (isFunction_default()(srcCondition) ? srcCondition(tagName) : tagName === srcCondition) { + nextBlock = current.childNodes.item(0); // there is no next blocktag + // eslint-disable-next-line max-depth + + if (!dom["a" /* default */].isElemNode(nextBlock) || current.childNodes.length > 1) { + nextBlock = _this2.createDefaultBlock(); + toArray_default()(current.childNodes).forEach(appendChidToNextBlock); + lastNodeOfNextBlock = nextBlock.lastChild; // remove unneccesary br + // eslint-disable-next-line max-depth + + if (lastNodeOfNextBlock && dom["a" /* default */].getNodeName(lastNodeOfNextBlock) === 'BR') { + nextBlock.removeChild(lastNodeOfNextBlock); + } + } // eslint-disable-next-line max-depth + + + if (targetTagName) { + newBlock = _this2.createElement(targetTagName, [nextBlock]); + } else { + newBlock = nextBlock; + } + + newFrag = _this2.getDocument().createDocumentFragment(); + newFrag.appendChild(newBlock); + frag = newFrag; + break; + } + + current = current.parentNode; + } + } // if source condition node is not founded, we wrap current div node with node named targetTagName + + + if ((!newFrag || !srcCondition) && targetTagName && dom["a" /* default */].getNodeName(frag.childNodes[0]) === 'DIV') { + frag = _this2.createElement(targetTagName, [frag.childNodes[0]]); + } + + return frag; + }); + }; + + _proto.changeBlockFormatTo = function changeBlockFormatTo(targetTagName) { + this.changeBlockFormat(function (tagName) { + return FIND_BLOCK_TAGNAME_RX.test(tagName); + }, targetTagName); + }; + + _proto.getCaretPosition = function getCaretPosition() { + return this.getCursorPosition(); + }; + + _proto.replaceSelection = function replaceSelection(content, selection) { + if (selection) { + this.setSelection(selection); + } + + this._ignoreChange = true; + this.insertHTML(content); + }; + + _proto.replaceRelativeOffset = function replaceRelativeOffset(content, offset, overwriteLength) { + var selection = this.getSelection().cloneRange(); + + this._replaceRelativeOffsetOfSelection(content, offset, overwriteLength, selection); + }; + + _proto._replaceRelativeOffsetOfSelection = function _replaceRelativeOffsetOfSelection(content, offset, overwriteLength, selection) { + var startSelectionInfo, endSelectionInfo, finalOffset; + var endOffsetNode = selection.endContainer; + var endTextOffset = selection.endOffset; + + if (dom["a" /* default */].getNodeName(endOffsetNode) !== 'TEXT') { + endOffsetNode = this._getClosestTextNode(endOffsetNode, endTextOffset); + + if (endOffsetNode) { + if (dom["a" /* default */].isTextNode(endOffsetNode)) { + endTextOffset = endOffsetNode.nodeValue.length; + } else { + endTextOffset = endOffsetNode.textContent.length; + } + } + } + + if (endOffsetNode) { + startSelectionInfo = this.getSelectionInfoByOffset(endOffsetNode, endTextOffset + offset); + selection.setStart(startSelectionInfo.element, startSelectionInfo.offset); + finalOffset = endTextOffset + (offset + overwriteLength); + endSelectionInfo = this.getSelectionInfoByOffset(endOffsetNode, finalOffset); + selection.setEnd(endSelectionInfo.element, endSelectionInfo.offset); + this.replaceSelection(content, selection); + } else { + this.replaceSelection(content); + } + }; + + _proto._getClosestTextNode = function _getClosestTextNode(node, offset) { + var foundNode = dom["a" /* default */].getChildNodeByOffset(node, offset - 1); + + if (dom["a" /* default */].getNodeName(foundNode) !== 'TEXT') { + foundNode = foundNode.previousSibling; + } + + return foundNode; + }; + + _proto.getSelectionInfoByOffset = function getSelectionInfoByOffset(anchorElement, offset) { + var traceElement, traceElementLength, traceOffset, stepLength; + var direction = offset >= 0 ? 'next' : 'previous'; + var offsetAbs = Math.abs(offset); + var latestAvailableElement = traceElement; + + if (direction === 'next') { + traceElement = anchorElement; + } else { + traceElement = anchorElement.previousSibling; + } + + traceOffset = offsetAbs; + stepLength = 0; + + while (traceElement) { + if (dom["a" /* default */].isTextNode(traceElement)) { + traceElementLength = traceElement.nodeValue.length; + } else { + traceElementLength = traceElement.textContent.length; + } + + stepLength += traceElementLength; + + if (offsetAbs <= stepLength) { + break; + } + + traceOffset -= traceElementLength; + + if (dom["a" /* default */].getTextLength(traceElement) > 0) { + latestAvailableElement = traceElement; + } + + traceElement = traceElement[direction + "Sibling"]; + } + + if (!traceElement) { + traceElement = latestAvailableElement; + traceOffset = dom["a" /* default */].getTextLength(traceElement); + } + + if (direction === 'previous') { + traceOffset = dom["a" /* default */].getTextLength(traceElement) - traceOffset; + } + + return { + element: traceElement, + offset: traceOffset + }; + }; + + _proto.getSelectionPosition = function getSelectionPosition(selection, style, offset) { + var marker = this.createElement('INPUT'); + var range = selection.cloneRange(); + var endSelectionInfo = this.getSelectionInfoByOffset(selection.endContainer, selection.endOffset + (offset || 0)); + range.setStart(range.startContainer, range.startOffset); + range.setEnd(endSelectionInfo.element, endSelectionInfo.offset); // to prevent squire input event fire + + this._ignoreChange = true; + this.insertElement(marker, range); + var pos = dom["a" /* default */].getOffset(marker); + + if (style !== 'over') { + pos.top += marker.offsetHeight; + } + + marker.parentNode.removeChild(marker); + selection.setStart(selection.endContainer, selection.endOffset); + selection.collapse(true); + this.setSelection(selection); + return pos; + }; + + _proto.removeLastUndoStack = function removeLastUndoStack() { + if (this._undoStack.length) { + this._undoStackLength -= 1; + this._undoIndex -= 1; + + this._undoStack.pop(); + + this._isInUndoState = false; + } + }; + + _proto.replaceParent = function replaceParent(node, from, to) { + var target = dom["a" /* default */].closest(node, from, this.getBody()); + + if (target) { + dom["a" /* default */].wrapInner(target, to); + dom["a" /* default */].unwrap(target); + } + }; + + _proto.preserveLastLine = function preserveLastLine() { + var blocks = this.getBody().children; + var lastBlock = blocks[blocks.length - 1]; + + if (lastBlock && dom["a" /* default */].getNodeName(lastBlock) !== 'DIV') { + this._ignoreChange = true; + dom["a" /* default */].insertAfter(this.createDefaultBlock(), lastBlock); + } + }; + + _proto.scrollTop = function scrollTop(top) { + if (!isUndefined_default()(top)) { + this.getBody().scrollTop = top; + } + + return this.getBody().scrollTop; + }; + + _proto.isIgnoreChange = function isIgnoreChange() { + return this._ignoreChange; + }; + + _proto.focus = function focus() { + squire_default.a.prototype.focus.call(this); + }; + + _proto.blockCommandShortcuts = function blockCommandShortcuts() { + var _this3 = this; + + var meta = utils_common["b" /* isMac */] ? 'meta' : 'ctrl'; + var keys = ['b', 'i', 'u', 'shift-7', 'shift-5', 'shift-6', 'shift-8', 'shift-9', '[', ']', 'd']; + keys.forEach(function (key) { + _this3.setKeyHandler(meta + "-" + key, function (editor, keyboardEvent) { + keyboardEvent.preventDefault(); + }); + }); + }; + + return SquireExt; +}(squire_default.a); + +/* harmony default export */ var squireExt = (squireExt_SquireExt); +// CONCATENATED MODULE: ./src/js/wwTextObject.js +/** + * @fileoverview Implements WwTextObject + * @author NHN FE Development Lab + */ + + +var isIE11 = browser_default.a.msie && browser_default.a.version === 11; +var isWindowChrome = navigator.appVersion.indexOf('Win') !== -1 && browser_default.a.chrome; +var isWindows10 = /Windows (NT )?10/g.test(navigator.appVersion); +var isNeedOffsetFix = isIE11 || isWindowChrome && !isWindows10; +/** + * Class WwTextObject + * @param {WysiwygEditor} wwe - wysiwygEditor + * @param {Range} range - Range object + */ + +var wwTextObject_WwTextObject = /*#__PURE__*/function () { + function WwTextObject(wwe, range) { + this._wwe = wwe; // msie11 and window chrome can't make start offset of range api correctly when compositing korean. + // so we need fix this when compositing korean.(and maybe other languages that needs composition.) + + if (isNeedOffsetFix) { + this.isComposition = false; + + this._initCompositionEvent(); + } + + this.setRange(range || this._wwe.getRange()); + } + /** + * Initialize composition event + * @private + */ + + + var _proto = WwTextObject.prototype; + + _proto._initCompositionEvent = function _initCompositionEvent() { + var _this = this; + + this._wwe.getEditor().addEventListener('compositionstart', function () { + _this.isComposition = true; + }); + + this._wwe.getEditor().addEventListener('compositionend', function () { + _this.isComposition = false; + }); + } + /** + * Set _range object to given range object + * @param {Range} range Range object + */ + ; + + _proto.setRange = function setRange(range) { + if (this._range) { + this._range.detach(); + } + + this._range = range; + } + /** + * Expand start offset by one + */ + ; + + _proto.expandStartOffset = function expandStartOffset() { + var range = this._range; + + if (dom["a" /* default */].isTextNode(range.startContainer) && range.startOffset > 0) { + range.setStart(range.startContainer, range.startOffset - 1); + } + } + /** + * Expand end offset by one + */ + ; + + _proto.expandEndOffset = function expandEndOffset() { + var range = this._range; + + if (dom["a" /* default */].isTextNode(range.endContainer) && range.endOffset < range.endContainer.nodeValue.length) { + range.setEnd(range.endContainer, range.endOffset + 1); + } + } + /** + * setEnd range on start + * @param {Range} range Range object + */ + ; + + _proto.setEndBeforeRange = function setEndBeforeRange(range) { + var offset = range.startOffset; + + if (this.isComposition) { + offset += 1; + } + + this._range.setEnd(range.startContainer, offset); + } + /** + * Get text content + * @returns {string} + */ + ; + + _proto.getTextContent = function getTextContent() { + return this._range.cloneContents().textContent; + } + /** + * Replace current selection content to given text + * @param {string} content Text content + */ + ; + + _proto.replaceContent = function replaceContent(content) { + this._wwe.getEditor().setSelection(this._range); + + this._wwe.getEditor().insertHTML(content); // When range is in table, 'insertHTML' makes div in table. + // So after 'insertHTML', div in table should be unwrap. + // 'wysiwygRangeChangeAfter' event let wwTableManager call '_unwrapBlockInTable' + + + if (this._wwe.isInTable(this._range)) { + this._wwe.eventManager.emit('wysiwygRangeChangeAfter', this._wwe); + } + + this._range = this._wwe.getRange(); + } + /** + * Delete current selection content + */ + ; + + _proto.deleteContent = function deleteContent() { + this._wwe.getEditor().setSelection(this._range); + + this._wwe.getEditor().insertHTML(''); + + this._range = this._wwe.getRange(); + } + /** + * Peek previous element's content + * @param {number} offset Offset to peek + * @returns {string} + */ + ; + + _proto.peekStartBeforeOffset = function peekStartBeforeOffset(offset) { + var range = this._range.cloneRange(); + + range.setStart(range.startContainer, Math.max(range.startOffset - offset, 0)); + range.setEnd(this._range.startContainer, this._range.startOffset); + return range.cloneContents().textContent; + }; + + return WwTextObject; +}(); + +/* harmony default export */ var wwTextObject = (wwTextObject_WwTextObject); +// CONCATENATED MODULE: ./src/js/ui/blockOverlay.js +/** + * @fileoverview Implements UI block overlay + * @author NHN FE Development Lab + */ + + +/** + * Class BlockOverlay + * @param {Object} options - options + * @param {EventManager} options.eventManager - event manager instance + * @param {HTMLElement} options.container - container element + * @param {string} options.attachedSelector - selector string to find attached element + * @ignore + */ + +var blockOverlay_BlockOverlay = /*#__PURE__*/function () { + function BlockOverlay(_ref) { + var eventManager = _ref.eventManager, + container = _ref.container, + attachedSelector = _ref.attachedSelector; + this._eventManager = eventManager; + this._attachedSelector = "[contenteditable=true] " + attachedSelector; + this._container = container; + this._attachedElement = null; + /** + * is activated. + * if this blockOverlay is active, It always be visible unconditionally. + * @type {boolean} + * @private + */ + + this.active = false; + + this._createElement(); + + this._initEvent(); + } + + var _proto = BlockOverlay.prototype; + + _proto._createElement = function _createElement() { + this.el = dom["a" /* default */].createElementWith('
    '); + css_default()(this.el, { + position: 'absolute', + display: 'none', + zIndex: 1 + }); + dom["a" /* default */].append(this._container, this.el); + }; + + _proto._initEvent = function _initEvent() { + var _this = this; + + this._eventManager.listen('change', this._onChange.bind(this)); + + this._eventManager.listen('mouseover', this._onMouseOver.bind(this)); + + this._eventManager.listen('focus', function () { + _this.setVisibility(false); + }); + + this._eventManager.listen('mousedown', function () { + _this.setVisibility(false); + }); + }; + + _proto._onChange = function _onChange() { + if (this._attachedElement && dom["a" /* default */].isContain(document.body, this._attachedElement)) { + this.syncLayout(); + } else { + this.setVisibility(false); + } + }; + + _proto._onMouseOver = function _onMouseOver(ev) { + var originalEvent = ev.data; + var eventTarget = originalEvent.target; + var attachedElement = dom["a" /* default */].closest(eventTarget, this._attachedSelector); + + if (attachedElement) { + this._attachedElement = attachedElement; + this.setVisibility(true); + } else if (dom["a" /* default */].closest(eventTarget, this.el)) { + this.setVisibility(true); + } else if (!this.active) { + this.setVisibility(false); + } + } + /** + * update blockOverlay position & size update to attached element + * you may want to override this to adjust position & size + * @protected + */ + ; + + _proto.syncLayout = function syncLayout() { + var offset = dom["a" /* default */].getOffset(this._attachedElement); + var outerWidth = dom["a" /* default */].getOuterWidth(this._attachedElement); + var outerHeight = dom["a" /* default */].getOuterHeight(this._attachedElement); + dom["a" /* default */].setOffset(this.el, offset); + css_default()(this.el, { + width: outerWidth + "px" + }); + css_default()(this.el, { + height: outerHeight + "px" + }); + } + /** + * attached element + * @protected + * @returns {HTMLElement} - attached element + */ + ; + + _proto.getAttachedElement = function getAttachedElement() { + return this._attachedElement || null; + } + /** + * visibility + * @protected + * @returns {boolean} visibility + */ + ; + + _proto.getVisibility = function getVisibility() { + return this.el.style.display === 'block'; + } + /** + * visibility + * @param {boolean} visibility - is visible + * @protected + */ + ; + + _proto.setVisibility = function setVisibility(visibility) { + if (visibility && this._attachedElement) { + if (!this.getVisibility()) { + css_default()(this.el, { + display: 'block' + }); + this.syncLayout(); + this.onShow(); + } + } else if (!visibility) { + if (this.getVisibility()) { + css_default()(this.el, { + display: 'none' + }); + this.onHide(); + } + } + } + /** + * called on show. you may want to override to get the event + * @protected + * @abstract + */ + ; + + _proto.onShow = function onShow() {} + /** + * called on hide. you may want to override to get the event + * @protected + */ + ; + + _proto.onHide = function onHide() { + this.active = false; + this._attachedElement = null; + }; + + return BlockOverlay; +}(); + +/* harmony default export */ var blockOverlay = (blockOverlay_BlockOverlay); +// CONCATENATED MODULE: ./src/js/ui/codeBlockGadget.js +function codeBlockGadget_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements UI code block gadget + * @author NHN FE Development Lab + */ + + + + + + +var GADGET_RIGHT = 26; +var GADGET_WIDTH = 250; +var GADGET_HEIGHT = 30; +/** + * Class CodeBlockGadget + * @param {Object} options - options + * @param {EventManager} options.eventManager - event manager instance + * @param {HTMLElement} options.container - container element + * @param {WysiwygEditor} options.wysiwygEditor - wysiwyg editor instance + * @ignore + */ + +var codeBlockGadget_CodeBlockGadget = /*#__PURE__*/function (_BlockOverlay) { + codeBlockGadget_inheritsLoose(CodeBlockGadget, _BlockOverlay); + + function CodeBlockGadget(_ref) { + var _this; + + var eventManager = _ref.eventManager, + container = _ref.container, + wysiwygEditor = _ref.wysiwygEditor; + _this = _BlockOverlay.call(this, { + eventManager: eventManager, + container: container, + attachedSelector: 'pre' + }) || this; + _this._wysiwygEditor = wysiwygEditor; + _this._popupCodeBlockLanguages = null; + + _this._initDOM(); + + _this._initDOMEvent(); + + return _this; + } + + var _proto = CodeBlockGadget.prototype; + + _proto._initDOM = function _initDOM() { + var _this2 = this; + + addClass_default()(this.el, 'code-block-header'); + this._languageLabel = dom["a" /* default */].createElementWith('text'); + dom["a" /* default */].append(this.el, this._languageLabel); + this._buttonOpenModalEditor = dom["a" /* default */].createElementWith(""); + dom["a" /* default */].append(this.el, this._buttonOpenModalEditor); + + this._eventManager.emit('removeEditor', function () { + off_default()(_this2._buttonOpenModalEditor, 'click'); + _this2._buttonOpenModalEditor = null; + }); + }; + + _proto._initDOMEvent = function _initDOMEvent() { + var _this3 = this; + + on_default()(this._buttonOpenModalEditor, 'click', function () { + return _this3._openPopupCodeBlockEditor(); + }); + }; + + _proto._openPopupCodeBlockEditor = function _openPopupCodeBlockEditor() { + this._eventManager.emit('openPopupCodeBlockEditor', this.getAttachedElement()); + }; + + _proto._updateLanguage = function _updateLanguage() { + var attachedElement = this.getAttachedElement(); + var language = attachedElement ? attachedElement.getAttribute('data-language') : null; + this._languageLabel.textContent = language || 'text'; + } + /** + * update gadget position + * @protected + * @override + */ + ; + + _proto.syncLayout = function syncLayout() { + var attachedElement = this.getAttachedElement(); + + var _domUtils$getOffset = dom["a" /* default */].getOffset(attachedElement, '.te-editor'), + top = _domUtils$getOffset.top; + + css_default()(this.el, { + top: top + "px", + right: GADGET_RIGHT + "px", + width: GADGET_WIDTH + "px", + height: GADGET_HEIGHT + "px" + }); + } + /** + * on show + * @protected + * @override + */ + ; + + _proto.onShow = function onShow() { + var _this4 = this; + + _BlockOverlay.prototype.onShow.call(this); + + this._onAttachedElementChange = function () { + return _this4._updateLanguage(); + }; + + this._eventManager.listen('changeLanguage', this._onAttachedElementChange); + + this._updateLanguage(); + } + /** + * on hide + * @protected + * @override + */ + ; + + _proto.onHide = function onHide() { + this._eventManager.removeEventHandler('changeLanguage', this._onAttachedElementChange); + + _BlockOverlay.prototype.onHide.call(this); + }; + + return CodeBlockGadget; +}(blockOverlay); + +/* harmony default export */ var codeBlockGadget = (codeBlockGadget_CodeBlockGadget); +// CONCATENATED MODULE: ./src/js/wysiwygEditor.js +/** + * @fileoverview Implments wysiwygEditor + * @author NHN FE Development Lab + */ + + + + + + + + + + + + + + + + + + + + + + + + + + + +var wysiwygEditor_keyMapper = keyMapper.getSharedInstance(); +var FIND_EMPTY_LINE = /<([a-z]+|h\d)>(
    |
    )<\/\1>/gi; +var FIND_UNNECESSARY_BR = /(?:
    |
    )<\/(.+?)>/gi; +var wysiwygEditor_FIND_BLOCK_TAGNAME_RX = /\b(H[\d]|LI|P|BLOCKQUOTE|TD|PRE)\b/; +var FIND_OPENING_SPAN_WITH_SPACE = /]*)>[\u0020]/g; +var FIND_CLOSING_SPAN_WITH_SPACE = /[\u0020]<\/span>/g; +var FIND_TABLE_AND_HEADING_RX = /^(TABLE|H[1-6])$/; +var EDITOR_CONTENT_CSS_CLASSNAME = 'tui-editor-contents'; +var PLACEHOLDER_CSS_CLASSNAME = 'tui-editor-contents-placeholder'; +var canObserveMutations = typeof MutationObserver !== 'undefined'; +/** + * Class WysiwygEditor + * @param {HTMLElement} el - element to insert editor + * @param {EventManager} eventManager - EventManager instance + */ + +var wysiwygEditor_WysiwygEditor = /*#__PURE__*/function () { + function WysiwygEditor(el, eventManager, options) { + var _this = this; + + if (options === void 0) { + options = {}; + } + + this.componentManager = new componentManager(this); + this.eventManager = eventManager; + this.editorContainerEl = el; + this._height = 0; + this._silentChange = false; + this._keyEventHandlers = {}; + this._managers = {}; + this._linkAttribute = options.linkAttribute || {}; + this._sanitizer = options.sanitizer; + + this._initEvent(); + + this._initDefaultKeyEventHandler(); + + this.debouncedPostProcessForChange = debounce_default()(function () { + return _this.postProcessForChange(); + }, 0); + } + /** + * init + */ + + + var _proto = WysiwygEditor.prototype; + + _proto.init = function init() { + var editorBody = document.createElement('div'); + this.editorContainerEl.appendChild(editorBody); + this.editor = new squireExt(editorBody, { + blockTag: 'DIV', + leafNodeNames: { + HR: false + }, + allowedBlocks: this._sanitizer ? [] : ['details', 'summary'] + }); + this.editor.blockCommandShortcuts(); + this._clipboardManager = new wwClipboardManager(this); + + this._initSquireEvent(); + + this._clipboardManager.init(); + + addClass_default()(this.getBody(), EDITOR_CONTENT_CSS_CLASSNAME); + css_default()(this.editorContainerEl, 'position', 'relative'); + + this._togglePlaceholder(); + + this.codeBlockGadget = new codeBlockGadget({ + eventManager: this.eventManager, + container: this.editorContainerEl, + wysiwygEditor: this + }); + } + /** + * Initialize EventManager event handler + * @private + */ + ; + + _proto._initEvent = function _initEvent() { + var _this2 = this; + + this.eventManager.listen('wysiwygKeyEvent', function (ev) { + return _this2._runKeyEventHandlers(ev.data, ev.keyMap); + }); + this.eventManager.listen('wysiwygRangeChangeAfter', function () { + return _this2.scrollIntoCursor(); + }); + this.eventManager.listen('contentChangedFromWysiwyg', function () { + _this2._togglePlaceholder(); + }); + } + /** + * Add key event handler + * @param {string|Array.} keyMap - keyMap string or array of string + * @param {function} handler handler + */ + ; + + _proto.addKeyEventHandler = function addKeyEventHandler(keyMap, handler) { + var _this3 = this; + + if (!handler) { + handler = keyMap; + keyMap = 'DEFAULT'; + } + + if (!isArray_default()(keyMap)) { + keyMap = [keyMap]; + } + + keyMap.forEach(function (key) { + if (!_this3._keyEventHandlers[key]) { + _this3._keyEventHandlers[key] = []; + } + + _this3._keyEventHandlers[key].push(handler); + }); + } + /** + * Remove key event handler. + * @param {string} keyMap keyMap string + * @param {function} handler handler + */ + ; + + _proto.removeKeyEventHandler = function removeKeyEventHandler(keyMap, handler) { + if (!handler) { + handler = keyMap; + keyMap = 'DEFAULT'; + } + + var handlers = this._keyEventHandlers[keyMap]; + + if (handlers) { + this._keyEventHandlers[keyMap] = handlers.filter(function (_handler) { + return _handler !== handler; + }); + } + } + /** + * Run key event handler + * @param {Event} event event object + * @param {string} keyMap keyMapString + * @private + */ + ; + + _proto._runKeyEventHandlers = function _runKeyEventHandlers(event, keyMap) { + var range = this.getRange(); + var handlers, isNeedNext; + handlers = this._keyEventHandlers.DEFAULT; + + if (handlers) { + forEachArray_default()(handlers, function (handler) { + isNeedNext = handler(event, range, keyMap); + return isNeedNext; + }); + } + + handlers = this._keyEventHandlers[keyMap]; + + if (handlers && isNeedNext !== false) { + forEachArray_default()(handlers, function (handler) { + return handler(event, range, keyMap); + }); + } + } + /** + * Initialize squire event + * @private + */ + ; + + _proto._initSquireEvent = function _initSquireEvent() { + var _this4 = this; + + var squire = this.getEditor(); + var isNeedFirePostProcessForRangeChange = false; + squire.addEventListener('copy', function (clipboardEvent) { + _this4.eventManager.emit('copy', { + source: 'wysiwyg', + data: clipboardEvent + }); + + debounce_default()(function () { + if (!_this4.isEditorValid()) { + return; + } + + _this4.eventManager.emit('copyAfter', { + source: 'wysiwyg', + data: clipboardEvent + }); + })(); + }); + squire.addEventListener(browser_default.a.msie ? 'beforecut' : 'cut', function (clipboardEvent) { + _this4.eventManager.emit('cut', { + source: 'wysiwyg', + data: clipboardEvent + }); + + debounce_default()(function () { + if (!_this4.isEditorValid()) { + return; + } + + _this4.eventManager.emit('cutAfter', { + source: 'wysiwyg', + data: clipboardEvent + }); + })(); + }); + squire.addEventListener(browser_default.a.msie ? 'beforepaste' : 'paste', function (clipboardEvent) { + _this4.eventManager.emit('paste', { + source: 'wysiwyg', + data: clipboardEvent + }); + }); + squire.addEventListener('dragover', function (ev) { + ev.preventDefault(); + return false; + }); + squire.addEventListener('drop', function (ev) { + ev.preventDefault(); + + _this4.eventManager.emit('drop', { + source: 'wysiwyg', + data: ev + }); + + return false; + }); // change event will fired after range has been updated + + squire.addEventListener('input', debounce_default()(function () { + if (!_this4.isEditorValid()) { + return; + } + + if (!_this4._silentChange) { + var eventObj = { + source: 'wysiwyg' + }; + + _this4.eventManager.emit('changeFromWysiwyg', eventObj); + + _this4.eventManager.emit('change', eventObj); + + _this4.eventManager.emit('contentChangedFromWysiwyg', _this4); + } else { + _this4._silentChange = false; + } + + _this4.getEditor().preserveLastLine(); + }, 0)); + squire.addEventListener('keydown', function (keyboardEvent) { + var range = _this4.getEditor().getSelection(); + + if (!range.collapsed) { + isNeedFirePostProcessForRangeChange = true; + } + + _this4.eventManager.emit('keydown', { + source: 'wysiwyg', + data: keyboardEvent + }); + + _this4._onKeyDown(keyboardEvent); + }); + + if (browser_default.a.firefox) { + squire.addEventListener('keypress', function (keyboardEvent) { + var keyCode = keyboardEvent.keyCode; + + if (keyCode === 13 || keyCode === 9) { + var range = _this4.getEditor().getSelection(); + + if (!range.collapsed) { + isNeedFirePostProcessForRangeChange = true; + } + + _this4.eventManager.emit('keydown', { + source: 'wysiwyg', + data: keyboardEvent + }); + + _this4._onKeyDown(keyboardEvent); + } + }); // firefox produces shattered text nodes + + squire.addEventListener('keyup', function () { + var range = _this4.getRange(); + + if (dom["a" /* default */].isTextNode(range.commonAncestorContainer) && dom["a" /* default */].isTextNode(range.commonAncestorContainer.previousSibling)) { + var prevLen = range.commonAncestorContainer.previousSibling.length; + var curEl = range.commonAncestorContainer; + range.commonAncestorContainer.previousSibling.appendData(range.commonAncestorContainer.data); + range.setStart(range.commonAncestorContainer.previousSibling, prevLen + range.startOffset); + range.collapse(true); + dom["a" /* default */].remove(curEl); + + _this4.setRange(range); + + range.detach(); + } + }); + } + + squire.addEventListener('keyup', function (keyboardEvent) { + if (isNeedFirePostProcessForRangeChange) { + _this4.debouncedPostProcessForChange(); + + isNeedFirePostProcessForRangeChange = false; + } + + _this4.eventManager.emit('keyup', { + source: 'wysiwyg', + data: keyboardEvent + }); + }); + on_default()(this.editorContainerEl, 'scroll', function (ev) { + _this4.eventManager.emit('scroll', { + source: 'wysiwyg', + data: ev + }); + }); + squire.addEventListener('click', function (ev) { + _this4.eventManager.emit('click', { + source: 'wysiwyg', + data: ev + }); + }); + squire.addEventListener('mousedown', function (ev) { + _this4.eventManager.emit('mousedown', { + source: 'wysiwyg', + data: ev + }); + }); + squire.addEventListener('mouseover', function (ev) { + _this4.eventManager.emit('mouseover', { + source: 'wysiwyg', + data: ev + }); + }); + squire.addEventListener('mouseout', function (ev) { + _this4.eventManager.emit('mouseout', { + source: 'wysiwyg', + data: ev + }); + }); + squire.addEventListener('mouseup', function (ev) { + _this4.eventManager.emit('mouseup', { + source: 'wysiwyg', + data: ev + }); + }); + squire.addEventListener('contextmenu', function (ev) { + _this4.eventManager.emit('contextmenu', { + source: 'wysiwyg', + data: ev + }); + }); + squire.addEventListener('focus', function () { + _this4.eventManager.emit('focus', { + source: 'wysiwyg' + }); + }); + squire.addEventListener('blur', function () { + _this4.fixIMERange(); + + _this4.eventManager.emit('blur', { + source: 'wysiwyg' + }); + }); // Toolbar status active/inactive + + squire.addEventListener('pathChange', function (data) { + var state = { + strong: /(^B>|>B$|>B>|^B$|STRONG)/.test(data.path), + emph: /(>I|>EM|^I$|^EM$)/.test(data.path), + strike: /(^S>|>S$|>S>|^S$|DEL)/.test(data.path), + code: /CODE/.test(data.path), + codeBlock: /PRE/.test(data.path), + blockQuote: /BLOCKQUOTE/.test(data.path), + table: /TABLE/.test(data.path), + heading: /H[1-6]/.test(data.path), + list: /UL>LI(?!.task-list-item)/.test(data.path), + orderedList: /OL>LI(?!.task-list-item)/.test(data.path), + taskList: /[UL|OL]>LI.task-list-item/.test(data.path), + source: 'wysiwyg' + }; + + _this4.eventManager.emit('stateChange', state); + }); + squire.addEventListener('willPaste', function (ev) { + // ev has 'fragment' when event occurs from 'insertHTML' of squire + // ev has 'text' when event occurs from 'insertPlainText' of squire + if (ev.fragment) { + _this4.eventManager.emit('willPaste', { + source: 'wysiwyg', + data: ev + }); + } + }); + }; + + _proto._togglePlaceholder = function _togglePlaceholder() { + var squire = this.getEditor(); + squire.modifyDocument(function () { + var root = squire.getRoot(); + + if (root.textContent || root.childNodes.length > 1) { + root.classList.remove(PLACEHOLDER_CSS_CLASSNAME); + } else { + root.classList.add(PLACEHOLDER_CSS_CLASSNAME); + } + }); + } + /** + * Handler of keydown event + * @param {object} keyboardEvent Event object + * @private + */ + ; + + _proto._onKeyDown = function _onKeyDown(keyboardEvent) { + var keyMap = wysiwygEditor_keyMapper.convert(keyboardEvent); // to avoid duplicate event firing in firefox + + if (keyboardEvent.keyCode) { + this.eventManager.emit('keyMap', { + source: 'wysiwyg', + keyMap: keyMap, + data: keyboardEvent + }); + + if (!keyboardEvent.defaultPrevented) { + this.eventManager.emit('wysiwygKeyEvent', { + keyMap: keyMap, + data: keyboardEvent + }); + } + } + } + /** + * Initialize default event handler + * @private + */ + ; + + _proto._initDefaultKeyEventHandler = function _initDefaultKeyEventHandler() { + var _this5 = this; + + this.addKeyEventHandler('ENTER', function (ev, range) { + if (_this5._isInOrphanText(range)) { + // We need this cuz input text right after table make orphan text in webkit + _this5.defer(function () { + _this5._wrapDefaultBlockToOrphanTexts(); + + _this5.breakToNewDefaultBlock(range, 'before'); + }); + } + + _this5.defer(function () { + return _this5.scrollIntoCursor(); + }); + }); + this.addKeyEventHandler('TAB', function (ev) { + var sq = _this5.getEditor(); + + var range = sq.getSelection(); + + var isAbleToInput4Spaces = range.collapsed && _this5._isCursorNotInRestrictedAreaOfTabAction(sq); + + var isTextSelection = !range.collapsed && dom["a" /* default */].isTextNode(range.commonAncestorContainer); + ev.preventDefault(); + + if (isAbleToInput4Spaces || isTextSelection) { + sq.insertPlainText("\xA0\xA0\xA0\xA0"); + return false; + } + + return true; + }); + this.addKeyEventHandler('BACK_SPACE', function (ev, range, keymap) { + return _this5._handleRemoveKeyEvent(ev, range, keymap); + }); + this.addKeyEventHandler('DELETE', function (ev, range, keymap) { + return _this5._handleRemoveKeyEvent(ev, range, keymap); + }); + }; + + _proto._handleRemoveKeyEvent = function _handleRemoveKeyEvent(ev, range, keyMap) { + var sq = this.getEditor(); + + if (this._isStartHeadingOrTableAndContainsThem(range)) { + var keyStr = keyMap === 'BACK_SPACE' ? 'backspace' : 'delete'; + sq.removeAllFormatting(); + + sq._keyHandlers[keyStr](sq, ev, sq.getSelection()); + + sq.removeLastUndoStack(); + return false; + } + + return true; + }; + + _proto._isStartHeadingOrTableAndContainsThem = function _isStartHeadingOrTableAndContainsThem(range) { + var startContainer = range.startContainer, + startOffset = range.startOffset, + commonAncestorContainer = range.commonAncestorContainer, + collapsed = range.collapsed; + var root = this.getEditor().getRoot(); + var result = false; + + if (!collapsed && commonAncestorContainer === root) { + if (startContainer === root) { + result = FIND_TABLE_AND_HEADING_RX.test(dom["a" /* default */].getChildNodeByOffset(startContainer, startOffset).nodeName); + } else if (startOffset === 0) { + result = FIND_TABLE_AND_HEADING_RX.test(dom["a" /* default */].getParentUntil(startContainer, root).nodeName); + } + } + + return result; + }; + + _proto._wrapDefaultBlockToOrphanTexts = function _wrapDefaultBlockToOrphanTexts() { + var textNodes = toArray_default()(this.getBody().childNodes).filter(function (node) { + return dom["a" /* default */].isTextNode(node); + }); + dom["a" /* default */].getAllTextNode(this.getBody()); + textNodes.forEach(function (node) { + if (node.nextSibling && node.nextSibling.tagName === 'BR') { + dom["a" /* default */].remove(node.nextSibling); + } + + dom["a" /* default */].wrap(node, document.createElement('div')); + }); + } + /** + * check if range is orphan text + * @param {Range} range range + * @returns {boolean} result + * @private + */ + ; + + _proto._isInOrphanText = function _isInOrphanText(range) { + return range.startContainer.nodeType === Node.TEXT_NODE && range.startContainer.parentNode === this.getBody(); + } + /** + * Wrap default block to passed range + * @param {Range} range range + * @private + */ + ; + + _proto._wrapDefaultBlockTo = function _wrapDefaultBlockTo(range) { + this.saveSelection(range); + + this._joinSplitedTextNodes(); + + this.restoreSavedSelection(); + range = this.getRange(); + var textElem = range.startContainer; + var cursorOffset = range.startOffset; // after code below, range range is arranged by body + + var block = this.getEditor().createDefaultBlock([range.startContainer]); // range for insert block + + var insertTargetNode = dom["a" /* default */].getChildNodeByOffset(range.startContainer, range.startOffset); + + if (insertTargetNode) { + range.setStartBefore(insertTargetNode); + } else { + // only child in container + range.selectNodeContents(range.startContainer); + } + + range.collapse(true); + range.insertNode(block); // revert range to original node + + range.setStart(textElem, cursorOffset); + range.collapse(true); + this.setRange(range); + } + /** + * Join spliated text nodes + * @private + */ + ; + + _proto._joinSplitedTextNodes = function _joinSplitedTextNodes() { + var prevNode, lastGroup; + var nodesToRemove = []; + var textNodes = toArray_default()(this.getBody().childNodes).filter(function (node) { + return dom["a" /* default */].isTextNode(node); + }); + textNodes.forEach(function (node) { + if (prevNode === node.previousSibling) { + lastGroup.nodeValue += node.nodeValue; + nodesToRemove.push(node); + } else { + lastGroup = node; + } + + prevNode = node; + }); + dom["a" /* default */].remove(nodesToRemove); + } + /** + * Save current selection before modification + * @param {Range} range Range object + */ + ; + + _proto.saveSelection = function saveSelection(range) { + if (!range) { + range = this.getRange(); + } + + this.getEditor()._saveRangeToBookmark(range); + } + /** + * set selection by start/end container/offset + * @param {HTMLNode} startContainer - start container + * @param {Number} startOffset - start offset + * @param {HTMLNode} endContainer - end container + * @param {Number} endOffset - end offset + * @returns {Range} - range instance + */ + ; + + _proto.setSelectionByContainerAndOffset = function setSelectionByContainerAndOffset(startContainer, startOffset, endContainer, endOffset) { + var sq = this.getEditor(); + var range = sq.getSelection(); + range.setStart(startContainer, startOffset); + range.setEnd(endContainer, endOffset); + sq.setSelection(range); + return range; + } + /** + * Restore saved selection + */ + ; + + _proto.restoreSavedSelection = function restoreSavedSelection() { + this.setRange(this.getEditor()._getRangeAndRemoveBookmark()); + } + /** + * Reset wysiwyg editor + */ + ; + + _proto.reset = function reset() { + this.setValue(''); + } + /** + * Change current range block format to passed tag + * @param {string} targetTagName Target element tag name + */ + ; + + _proto.changeBlockFormatTo = function changeBlockFormatTo(targetTagName) { + this.getEditor().changeBlockFormatTo(targetTagName); + this.eventManager.emit('wysiwygRangeChangeAfter', this); + } + /** + * Make empty block to current selection + */ + ; + + _proto.makeEmptyBlockCurrentSelection = function makeEmptyBlockCurrentSelection() { + var _this6 = this; + + this.getEditor().modifyBlocks(function (frag) { + if (!frag.textContent) { + frag = _this6.getEditor().createDefaultBlock(); + } + + return frag; + }); + } + /** + * Focus to editor + */ + ; + + _proto.focus = function focus() { + var scrollTop = this.scrollTop(); + this.editor.focus(); // In webkit, if contenteditable element focus method have been invoked when another input element has focus, + // contenteditable scroll to top automatically so we need scroll it back + + if (scrollTop !== this.scrollTop()) { + this.scrollTop(scrollTop); + } + } + /** + * Remove focus of editor + */ + ; + + _proto.blur = function blur() { + this.editor.blur(); + } + /** + * Remove wysiwyg editor + */ + ; + + _proto.remove = function remove() { + off_default()(this.editorContainerEl, 'scroll'); + this.getEditor().destroy(); + this.editor = null; + this.body = null; + this.eventManager = null; + } + /** + * Set editor height + * @param {number|string} height pixel of height or "auto" + */ + ; + + _proto.setHeight = function setHeight(height) { + this._height = height; + css_default()(this.editorContainerEl, { + overflow: 'auto', + height: '100%' + }); + css_default()(this.editorContainerEl.parentNode, { + height: isNumber_default()(height) ? height + "px" : height + }); + var containerStyles = this.editorContainerEl.style; + var bodyStyles = this.getBody().style; + var paddingHeight = parseInt(containerStyles.paddingTop, 10) - parseInt(containerStyles.paddingBottom, 10); + var marginHeight = parseInt(bodyStyles.marginTop, 10) - parseInt(bodyStyles.marginBottom, 10); + css_default()(this.getBody(), { + minHeight: height - marginHeight - paddingHeight + "px" + }); + } + /** + * Set min height + * @param {number} minHeight - min height in px + */ + ; + + _proto.setMinHeight = function setMinHeight(minHeight) { + var editorBody = this.getBody(); + css_default()(editorBody, 'minHeight', minHeight + "px"); + } + /** + * Set the placeholder to wysiwyg editor + * @param {string} placeholder - placeholder to set + */ + ; + + _proto.setPlaceholder = function setPlaceholder(placeholder) { + if (placeholder) { + this.getEditor().getRoot().setAttribute('data-placeholder', placeholder); + } + } + /** + * Get attribute of link for wysiwyg + * @returns {object} attribute - attribute of anchor tag + */ + ; + + _proto.getLinkAttribute = function getLinkAttribute() { + return this._linkAttribute; + } + /** + * Set value to wysiwyg editor + * @param {string} html - HTML text + * @param {boolean} [cursorToEnd=true] - move cursor to contents end + */ + ; + + _proto.setValue = function setValue(html, cursorToEnd) { + if (cursorToEnd === void 0) { + cursorToEnd = true; + } + + html = this.eventManager.emitReduce('wysiwygSetValueBefore', html); + this.editor.setHTML(html); + this.eventManager.emit('wysiwygSetValueAfter', this); + this.eventManager.emit('contentChangedFromWysiwyg', this); + + if (cursorToEnd) { + this.moveCursorToEnd(); + } + + this.getEditor().preserveLastLine(); + this.getEditor().removeLastUndoStack(); + this.getEditor().saveUndoState(); + } + /** + * Insert given text to cursor position or selected area + * @param {string} text - text string to insert + */ + ; + + _proto.insertText = function insertText(text) { + this.editor.insertPlainText(text); + } + /** + * Get value of wysiwyg editor + * @returns {string} html + */ + ; + + _proto.getValue = function getValue() { + this._prepareGetHTML(); + + var html = this.editor.getHTML(); // empty line replace to br + + html = html.replace(FIND_EMPTY_LINE, function (match, tag) { + var result; // we maintain empty list + + if (tag === 'li') { + result = match; // we maintain empty table + } else if (tag === 'td' || tag === 'th') { + result = "<" + tag + ">"; + } else { + result = '
    '; + } + + return result; + }); // replace a space of the first and end in span tag to  . + + html = html.replace(FIND_OPENING_SPAN_WITH_SPACE, ' '); + html = html.replace(FIND_CLOSING_SPAN_WITH_SPACE, ' '); // remove unnecessary brs + + html = html.replace(FIND_UNNECESSARY_BR, ''); // remove contenteditable block, in this case div + + html = html.replace(/]*>/g, ''); + html = html.replace(/<\/div>/g, '
    '); + html = this.eventManager.emitReduce('wysiwygProcessHTMLText', html); + return html; + } + /** + * Prepare before get html + * @private + */ + ; + + _proto._prepareGetHTML = function _prepareGetHTML() { + var _this7 = this; + + this.getEditor().modifyDocument(function () { + _this7._joinSplitedTextNodes(); + + _this7.eventManager.emit('wysiwygGetValueBefore', _this7); + }); + } + /** + * postProcessForChange + */ + ; + + _proto.postProcessForChange = function postProcessForChange() { + var _this8 = this; + + if (!this.isEditorValid()) { + return; + } + + this.getEditor().modifyDocument(function () { + _this8.eventManager.emit('wysiwygRangeChangeAfter', _this8); + }); + } + /** + * Ready to silent change + */ + ; + + _proto.readySilentChange = function readySilentChange() { + if (canObserveMutations && !this.getEditor().isIgnoreChange()) { + this._silentChange = true; + } + } + /** + * Get squire + * @returns {SquireExt} squire + */ + ; + + _proto.getEditor = function getEditor() { + return this.editor; + } + /** + * Replace text of passed range + * @param {string} content Content for change current selection + * @param {Range} range range + */ + ; + + _proto.replaceSelection = function replaceSelection(content, range) { + this.getEditor().replaceSelection(content, range); + } + /** + * Replace content by relative offset + * @param {string} content Content for change current selection + * @param {number} offset Offset of current range + * @param {number} overwriteLength Length to overwrite content + */ + ; + + _proto.replaceRelativeOffset = function replaceRelativeOffset(content, offset, overwriteLength) { + this.getEditor().replaceRelativeOffset(content, offset, overwriteLength); + } + /** + * Add widget to selection + * @param {Range} range Range object + * @param {Node} node Widget node + * @param {string} style Adding style "over" or "bottom" + * @param {number} [offset] Offset to adjust position + */ + ; + + _proto.addWidget = function addWidget(range, node, style, offset) { + var pos = this.getEditor().getSelectionPosition(range, style, offset); + var editorContainerPos = dom["a" /* default */].getOffset(this.editorContainerEl); + this.editorContainerEl.appendChild(node); + css_default()(node, { + position: 'absolute', + top: pos.top - editorContainerPos.top + "px", + left: pos.left - editorContainerPos.left + "px" + }); + } + /** + * Get body container of Squire + * @returns {HTMLElement} body element + */ + ; + + _proto.getBody = function getBody() { + return this.getEditor().getBody(); + } + /** + * Check with given regexp whether current path has some format or not + * @param {RegExp} rx Regexp + * @returns {boolean} Match result + */ + ; + + _proto.hasFormatWithRx = function hasFormatWithRx(rx) { + return this.getEditor().getPath().match(rx); + } + /** + * Break line to new default block from passed range + * @param {Range} range Range object + * @param {string} [where] "before" or not + */ + ; + + _proto.breakToNewDefaultBlock = function breakToNewDefaultBlock(range, where) { + var div = this.editor.createDefaultBlock(); + var currentNode = dom["a" /* default */].getChildNodeByOffset(range.startContainer, range.startOffset) || dom["a" /* default */].getChildNodeByOffset(range.startContainer, range.startOffset - 1); + var appendBefore = dom["a" /* default */].getParentUntil(currentNode, this.getBody()); + + if (where === 'before') { + dom["a" /* default */].insertBefore(div, appendBefore); + } else { + dom["a" /* default */].insertAfter(div, appendBefore); + } + + range.setStart(div, 0); + range.collapse(true); + this.setRange(range); + } + /** + * Replace textContet of node + * @param {Node} container Container node + * @param {string} from Target text to change + * @param {string} to Replacement text + */ + ; + + _proto.replaceContentText = function replaceContentText(container, from, to) { + var beforeText = container.innerHTML; + container.innerHTML = beforeText.replace(from, to); + } + /** + * Unwrap Block tag of current range + * @param {function} [condition] iterate with tagName + */ + ; + + _proto.unwrapBlockTag = function unwrapBlockTag(condition) { + if (!condition) { + condition = function condition(tagName) { + return wysiwygEditor_FIND_BLOCK_TAGNAME_RX.test(tagName); + }; + } + + this.getEditor().changeBlockFormat(condition); + this.eventManager.emit('wysiwygRangeChangeAfter', this); + } + /** + * move scroll to cursor + * scrollIntoView browser function may cause scrolling on document. + * this function aims to replace scrollIntoView function to prevent that. + * it will move the scroll of squire only. + */ + ; + + _proto.scrollIntoCursor = function scrollIntoCursor() { + var scrollTop = this.scrollTop(); + + var _this$getEditor$getCu = this.getEditor().getCursorPosition(), + cursorTop = _this$getEditor$getCu.top, + cursorHeight = _this$getEditor$getCu.height; + + var _this$editorContainer = this.editorContainerEl.getBoundingClientRect(), + editorTop = _this$editorContainer.top, + editorHeight = _this$editorContainer.height; + + var cursorAboveEditor = cursorTop - editorTop; + var cursorBelowEditor = cursorTop + cursorHeight - (editorTop + editorHeight); + + if (cursorAboveEditor < 0) { + this.scrollTop(scrollTop + cursorAboveEditor); + } else if (cursorBelowEditor > 0) { + this.scrollTop(Math.ceil(scrollTop + cursorBelowEditor)); + } + } + /** + * Set cursor position to end + */ + ; + + _proto.moveCursorToEnd = function moveCursorToEnd() { + this.getEditor().moveCursorToEnd(); + this.scrollIntoCursor(); + + this._correctRangeAfterMoveCursor('end'); + } + /** + * Set cursor position to start + */ + ; + + _proto.moveCursorToStart = function moveCursorToStart() { + this.getEditor().moveCursorToStart(); + this.scrollTop(0); + } + /** + * Set cursor position to start + * @param {number} value Scroll amount + * @returns {number} value of scrollTop + */ + ; + + _proto.scrollTop = function scrollTop(value) { + if (!isUndefined_default()(value)) { + this.editorContainerEl.scrollTop = value; + } + + return this.editorContainerEl.scrollTop; + } + /** + * For arrange Range after moveCursorToEnd api invocation. Squire has bug in Firefox, IE. + * @param {string} direction Direction of cursor move + * @private + */ + ; + + _proto._correctRangeAfterMoveCursor = function _correctRangeAfterMoveCursor(direction) { + var range = this.getRange(); + var cursorContainer = this.getBody(); + + if (direction === 'start') { + while (cursorContainer.firstChild) { + cursorContainer = cursorContainer.firstChild; + } + } else { + while (cursorContainer.lastChild) { + cursorContainer = cursorContainer.lastChild; + } + } // IE have problem with cursor after br + + + if (cursorContainer.tagName === 'BR') { + range.setStartBefore(cursorContainer); + } else { + range.setStartAfter(cursorContainer); + } + + range.collapse(true); + this.setRange(range); + } + /** + * Get current Range object + * @returns {Range} + */ + ; + + _proto.getRange = function getRange() { + return this.getEditor().getSelection().cloneRange(); + } + /** + * get IME range + * cjk composition causes wrong caret position. + * it returns fixed IME composition range + * @returns {Range} + */ + ; + + _proto.getIMERange = function getIMERange() { + var range; + var selection = getSelection(); + + if (selection && selection.rangeCount) { + range = selection.getRangeAt(0).cloneRange(); + } + + return range; + } + /** + * get IME range + * cjk composition causes wrong caret position. + * it sets fixed IME composition range + */ + ; + + _proto.fixIMERange = function fixIMERange() { + var range = this.getIMERange(); // range exists and it's an WYSIWYG editor content + + if (range) { + var contentElement = dom["a" /* default */].getParentUntil(range.commonAncestorContainer, this.editorContainerEl); + var foundEditorElement = !!(contentElement && contentElement.parentNode); + + if (foundEditorElement) { + this.setRange(range); + } + } + } + /** + * set range + * @param {Range} range - range to set + */ + ; + + _proto.setRange = function setRange(range) { + this.getEditor().setSelection(range); + } + /** + * Check whether passed range is in table or not + * @param {Range} range range + * @returns {boolean} result + */ + ; + + _proto.isInTable = function isInTable(range) { + var target = range.collapsed ? range.startContainer : range.commonAncestorContainer; + return !!dom["a" /* default */].closest(target, '[contenteditable=true] table'); + } + /** + * Get text object of current range + * @param {Range} range Range object + * @returns {WwTextObject} + */ + ; + + _proto.getTextObject = function getTextObject(range) { + return new wwTextObject(this, range); + }; + + _proto.defer = function defer(callback, delayOffset) { + var _this9 = this; + + var delay = delayOffset ? delayOffset : 0; + setTimeout(function () { + if (_this9.isEditorValid()) { + callback(_this9); + } + }, delay); + }; + + _proto.isEditorValid = function isEditorValid() { + return this.getEditor() && dom["a" /* default */].isContain(document.body, this.editorContainerEl); + }; + + _proto._isCursorNotInRestrictedAreaOfTabAction = function _isCursorNotInRestrictedAreaOfTabAction(editor) { + return !editor.hasFormat('li') && !editor.hasFormat('blockquote') && !editor.hasFormat('table'); + }; + + _proto.getSanitizer = function getSanitizer() { + return this._sanitizer; + } + /** + * WysiwygEditor factory method + * @param {HTMLElement} el Container element for editor + * @param {EventManager} eventManager EventManager instance + * @param {object} [options={}] - option object + * @returns {WysiwygEditor} wysiwygEditor + * @ignore + */ + ; + + WysiwygEditor.factory = function factory(el, eventManager, options) { + var wwe = new WysiwygEditor(el, eventManager, options); + wwe.init(); + wwe.componentManager.addManager(wwLinkManager_WwLinkManager); + wwe.componentManager.addManager(wwListManager); + wwe.componentManager.addManager(wwTaskManager); + wwe.componentManager.addManager(wwTableSelectionManager); + wwe.componentManager.addManager(wwTableManager); + wwe.componentManager.addManager(wwHrManager); + wwe.componentManager.addManager(wwPManager); + wwe.componentManager.addManager(wwHeadingManager); + wwe.componentManager.addManager(wwCodeBlockManager); + return wwe; + }; + + return WysiwygEditor; +}(); + +/* harmony default export */ var wysiwygEditor = (wysiwygEditor_WysiwygEditor); +// CONCATENATED MODULE: ./src/js/layout.js +/** + * @fileoverview editor layout + * @author NHN FE Development Lab + */ + + + + +/** + * Editor container template + * @type {string} + * @ignore + */ + +var containerTmpl = ['
    ', '
    ', '
    ', '
    ', '
    ', '
    ', '
    ', '
    ', '
    ', '
    '].join(''); +/** + * Class Layout + * @param {object} options - Option object + * @param {EventManager} eventManager - Event manager instance + * @ignore + */ + +var layout_Layout = /*#__PURE__*/function () { + function Layout(options, eventManager) { + this.el = options.el; + this.height = options.height; + this.type = options.initialEditType; + this.eventManager = eventManager; + this.init(); + + this._initEvent(); + } + /** + * Initializer + * @protected + */ + + + var _proto = Layout.prototype; + + _proto.init = function init() { + this._renderLayout(); + + this._initMarkdownAndPreviewSection(); + + this._initWysiwygSection(); + } + /** + * Initialize show and hide event + * @private + */ + ; + + _proto._initEvent = function _initEvent() { + this.eventManager.listen('hide', this.hide.bind(this)); + this.eventManager.listen('show', this.show.bind(this)); + } + /** + * Create editor container with template + * @private + */ + ; + + _proto._renderLayout = function _renderLayout() { + css_default()(this.el, { + boxSizing: 'border-box' + }); + this.containerEl = dom["a" /* default */].createElementWith(containerTmpl, this.el); + } + /** + * Switch editor mode to WYSIWYG + */ + ; + + _proto.switchToWYSIWYG = function switchToWYSIWYG() { + removeClass_default()(this.containerEl, 'te-md-mode'); + addClass_default()(this.containerEl, 'te-ww-mode'); + } + /** + * Switch editor mode to Markdown + */ + ; + + _proto.switchToMarkdown = function switchToMarkdown() { + removeClass_default()(this.containerEl, 'te-ww-mode'); + addClass_default()(this.containerEl, 'te-md-mode'); + } + /** + * Initialize editor to Markdown and set preview section + * @private + */ + ; + + _proto._initMarkdownAndPreviewSection = function _initMarkdownAndPreviewSection() { + this.mdEditorContainerEl = this.containerEl.querySelector('.te-md-container .te-editor'); + this.previewEl = this.containerEl.querySelector('.te-md-container .te-preview'); + } + /** + * Initialize editor to WYSIWYG + * @private + */ + ; + + _proto._initWysiwygSection = function _initWysiwygSection() { + this.wwEditorContainerEl = this.containerEl.querySelector('.te-ww-container .te-editor'); + } + /** + * Set preview to vertical split style + * @private + */ + ; + + _proto._verticalSplitStyle = function _verticalSplitStyle() { + var mdContainer = this.containerEl.querySelector('.te-md-container'); + removeClass_default()(mdContainer, 'te-preview-style-tab'); + addClass_default()(mdContainer, 'te-preview-style-vertical'); + } + /** + * Set tab style preview mode + * @private + */ + ; + + _proto._tabStyle = function _tabStyle() { + var mdContainer = this.containerEl.querySelector('.te-md-container'); + removeClass_default()(mdContainer, 'te-preview-style-vertical'); + addClass_default()(mdContainer, 'te-preview-style-tab'); + } + /** + * Toggle preview style between tab and vertical split + * @param {string} style Preview style ('tab' or 'vertical') + */ + ; + + _proto.changePreviewStyle = function changePreviewStyle(style) { + if (style === 'tab') { + this._tabStyle(); + } else if (style === 'vertical') { + this._verticalSplitStyle(); + } + } + /** + * Hide Editor + */ + ; + + _proto.hide = function hide() { + addClass_default()(this.el.querySelector('.tui-editor'), 'te-hide'); + } + /** + * Show Editor + */ + ; + + _proto.show = function show() { + removeClass_default()(this.el.querySelector('.tui-editor'), 'te-hide'); + } + /** + * Remove Editor + */ + ; + + _proto.remove = function remove() { + dom["a" /* default */].remove(this.el.querySelector('.tui-editor')); + } + /** + * Get wrapped editor container element + * @returns {HTMLElement} + */ + ; + + _proto.getEditorEl = function getEditorEl() { + return this.containerEl; + } + /** + * Get wrapped preview element + * @returns {HTMLElement} + */ + ; + + _proto.getPreviewEl = function getPreviewEl() { + return this.previewEl; + } + /** + * Get wrapped Markdown editor element + * @returns {HTMLElement} + */ + ; + + _proto.getMdEditorContainerEl = function getMdEditorContainerEl() { + return this.mdEditorContainerEl; + } + /** + * Get wrapped WYSIWYG editor element + * @returns {HTMLElement} + */ + ; + + _proto.getWwEditorContainerEl = function getWwEditorContainerEl() { + return this.wwEditorContainerEl; + }; + + return Layout; +}(); + +/* harmony default export */ var js_layout = (layout_Layout); +// EXTERNAL MODULE: ./src/js/eventManager.js +var js_eventManager = __webpack_require__(36); + +// EXTERNAL MODULE: ./src/js/commandManager.js + 1 modules +var commandManager = __webpack_require__(1); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/array/inArray.js +var inArray = __webpack_require__(14); +var inArray_default = /*#__PURE__*/__webpack_require__.n(inArray); + +// CONCATENATED MODULE: ./src/js/importManager.js +/** + * @fileoverview Implement Module for managing import external data such as image + * @author NHN FE Development Lab + */ + + +var URLRegex = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})(\/([^\s]*))?$/g; +/** + * Class ImportManager + * @param {EventManager} eventManager - eventManager + * @ignore + */ + +var importManager_ImportManager = /*#__PURE__*/function () { + function ImportManager(eventManager) { + this.eventManager = eventManager; + + this._initEvent(); + + this._initDefaultImageImporter(); + } + /** + * graceful decode uri component + * @param {string} originalURI - string to be decoded + * @returns {string} decoded string + * @static + */ + + + ImportManager.decodeURIGraceful = function decodeURIGraceful(originalURI) { + var uris = originalURI.split(' '); + var decodedURIs = []; + var decodedURI; + forEachArray_default()(uris, function (uri) { + try { + decodedURI = decodeURIComponent(uri); + decodedURI = decodedURI.replace(/ /g, '%20'); + } catch (e) { + decodedURI = uri; + } + + return decodedURIs.push(decodedURI); + }); + return decodedURIs.join(' '); + } + /** + * encode markdown critical characters + * @param {string} text - string to encode + * @returns {string} - markdown character encoded string + * @static + */ + ; + + ImportManager.encodeMarkdownCharacters = function encodeMarkdownCharacters(text) { + return text.replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\[/g, '%5B').replace(/\]/g, '%5D').replace(//g, '%3E'); + } + /** + * escape markdown critical characters + * @param {string} text - string to escape + * @returns {string} - markdown character escaped string + * @static + */ + ; + + ImportManager.escapeMarkdownCharacters = function escapeMarkdownCharacters(text) { + return text.replace(/\(/g, '\\(').replace(/\)/g, '\\)').replace(/\[/g, '\\[').replace(/\]/g, '\\]').replace(//g, '\\>'); + } + /** + * Initialize event handler + * @private + */ + ; + + var _proto = ImportManager.prototype; + + _proto._initEvent = function _initEvent() { + var _this = this; + + this.eventManager.listen('drop', function (ev) { + var items = ev.data.dataTransfer && ev.data.dataTransfer.files; + + _this._processBlobItems(items, ev.data); + }); + this.eventManager.listen('willPaste', function (ev) { + // IE has no interface to handle clipboard image. #976 + var fragment = ev.data.fragment; + var descendant = fragment.querySelectorAll('*'); // only if paste event data has one img element and the element has base64 encoded image + + if (descendant.length !== 1 || descendant[0].tagName !== 'IMG' || !/^data:image/.test(descendant[0].src)) { + return; + } + + ev.data.preventDefault(); + var blob = dataURItoBlob(descendant[0].src); + + _this._emitAddImageBlobHook(blob, 'paste'); + }); + this.eventManager.listen('paste', function (ev) { + _this._processClipboard(ev.data); + }); + this.eventManager.listen('pasteBefore', function (ev) { + _this._decodeURL(ev); + }); + } + /** + * Initialize default image importer + * @private + */ + ; + + _proto._initDefaultImageImporter = function _initDefaultImageImporter() { + this.eventManager.listen('addImageBlobHook', function (blob, callback) { + var reader = new FileReader(); + + reader.onload = function (event) { + callback(event.target.result); + }; + + reader.readAsDataURL(blob); + }); + } + /** + * Emit add image blob hook + * @param {object} blob - blob or file + * @param {string} type - type of an event the item belongs to. paste or drop + * @private + */ + ; + + _proto._emitAddImageBlobHook = function _emitAddImageBlobHook(blob, type) { + var _this2 = this; + + this.eventManager.emit('addImageBlobHook', blob, function (imageUrl, altText) { + _this2.eventManager.emit('command', 'AddImage', { + imageUrl: imageUrl, + altText: altText || blob.name || 'image' + }); + }, type); + } + /** + * Decode url when paste link + * @param {object} ev - event object + * @private + */ + ; + + _proto._decodeURL = function _decodeURL(ev) { + var decodeURIGraceful = ImportManager.decodeURIGraceful, + encodeMarkdownCharacters = ImportManager.encodeMarkdownCharacters; + + if (ev.source === 'markdown' && ev.data.text) { + var texts = ev.data.text; + var text = texts[0]; + + if (texts.length === 1 && text.match(URLRegex)) { + text = decodeURIGraceful(text); + text = encodeMarkdownCharacters(text); + ev.data.update(null, null, [text]); + } + } else if (ev.source === 'wysiwyg') { + var container = ev.clipboardContainer; + var _container$childNodes = container.childNodes, + firstChild = _container$childNodes[0]; + var _text = firstChild.innerText; + + if (container.childNodes.length === 1 && firstChild.tagName === 'A' && _text.match(URLRegex)) { + firstChild.innerText = decodeURIGraceful(_text); + firstChild.href = encodeMarkdownCharacters(firstChild.href); + } + } + } + /** + * Get blob or excel data from clipboard + * @param {object} evData Clipboard data + * @private + */ + ; + + _proto._processClipboard = function _processClipboard(evData) { + var cbData = evData.clipboardData || window.clipboardData; + var blobItems = cbData && cbData.items; + var types = cbData.types; + + if (blobItems && types && types.length === 1 && inArray_default()('Files', [].slice.call(types)) !== -1) { + this._processBlobItems(blobItems, evData); + } + } + /** + * Process for blob item + * @param {Array.} items Item array + * @param {object} evData Event data + * @private + */ + ; + + _proto._processBlobItems = function _processBlobItems(items, evData) { + var _this3 = this; + + if (items) { + forEachArray_default()(items, function (item) { + if (item.type.indexOf('image') !== -1) { + evData.preventDefault(); + evData.stopPropagation(); + evData.codemirrorIgnore = true; + var blob = item.name ? item : item.getAsFile(); // Blob or File + + _this3._emitAddImageBlobHook(blob, evData.type); + + return false; + } + + return true; + }); + } + }; + + return ImportManager; +}(); +/** + * data URI to Blob + * @param {string} dataURI - data URI string + * @returns {Blob} - blob data + * @ignore + */ + + +function dataURItoBlob(dataURI) { + var byteString = atob(dataURI.split(',')[1]); + var ab = new ArrayBuffer(byteString.length); + var ia = new Uint8Array(ab); + + for (var i = 0; i < byteString.length; i += 1) { + ia[i] = byteString.charCodeAt(i); + } + + var _dataURI$split = dataURI.split(','), + mimeString = _dataURI$split[0]; + + var blob = new Blob([ab], { + type: mimeString.split(':')[1].split(';')[0] + }); + return blob; +} + +/* harmony default export */ var importManager = (importManager_ImportManager); +// EXTERNAL MODULE: ./src/js/convertor.js +var convertor = __webpack_require__(37); + +// EXTERNAL MODULE: ./src/js/viewer.js +var viewer = __webpack_require__(46); + +// EXTERNAL MODULE: ./src/js/utils/map.js +var map = __webpack_require__(23); + +// CONCATENATED MODULE: ./src/js/i18n.js +/** + * @fileoverview Implements i18n + * @author NHN FE Development Lab + */ + + +var DEFAULT_CODE = 'en-US'; +/** + * Class I18n + * @ignore + */ + +var i18n_I18n = /*#__PURE__*/function () { + function I18n() { + this._code = DEFAULT_CODE; + this._langs = new map["a" /* default */](); + } + /** + * Set locale code + * @param {string} code locale code + */ + + + var _proto = I18n.prototype; + + _proto.setCode = function setCode(code) { + this._code = code; + } + /** + * Set language set + * @param {string|string[]} codes locale code + * @param {object} data language set + */ + ; + + _proto.setLanguage = function setLanguage(codes, data) { + var _this = this; + + codes = [].concat(codes); + codes.forEach(function (code) { + if (!_this._langs.has(code)) { + _this._langs.set(code, data); + } else { + var langData = _this._langs.get(code); + + _this._langs.set(code, extend_default()(langData, data)); + } + }); + } + /** + * Get text of key + * @param {string} key key of text + * @param {string} code locale code + * @returns {string} + */ + ; + + _proto.get = function get(key, code) { + if (!code) { + code = this._code; + } + + var langSet = this._langs.get(code); + + if (!langSet) { + langSet = this._langs.get(DEFAULT_CODE); + } + + var text = langSet[key]; + + if (!text) { + throw new Error("There is no text key \"" + key + "\" in " + code); + } + + return text; + }; + + return I18n; +}(); + + +/* harmony default export */ var i18n = (new i18n_I18n()); +// EXTERNAL MODULE: ./node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js +var ResizeObserver_es = __webpack_require__(57); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/type/isString.js +var isString = __webpack_require__(9); +var isString_default = /*#__PURE__*/__webpack_require__.n(isString); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/type/isObject.js +var isObject = __webpack_require__(54); +var isObject_default = /*#__PURE__*/__webpack_require__.n(isObject); + +// EXTERNAL MODULE: ./node_modules/tui-code-snippet/customEvents/customEvents.js +var customEvents = __webpack_require__(58); +var customEvents_default = /*#__PURE__*/__webpack_require__.n(customEvents); + +// CONCATENATED MODULE: ./src/js/ui/uicontroller.js +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview Implements ui controller + * @author NHN FE Development Lab + */ + + + + + + + + +var DOM_EVENTS = ['click', 'mousedown', 'mousemove', 'mouseup', 'mouseover', 'mouseout', 'scroll']; + +var _uiInstanceId = -1; +/** + * get ui instance id + * @returns {number} - new instance id + * @ignore + */ + + +function makeUIInstanceId() { + _uiInstanceId += 1; + return _uiInstanceId; +} +/** + * Class UIController + * @param {Object} [options] - options + * @param {HTMLElement} [options.rootElement] - root element + * @param {string} [options.tagName] - tag name + * @param {string} [options.className] - class name + */ + + +var uicontroller_UIController = /*#__PURE__*/function () { + /** + * tag name + * @type {string} + */ + + /** + * ui controller class name + * @type {string} + */ + + /** + * UI element + * @type {Object} + */ + + /** + * UI Id + * @type {number} + * @private + */ + function UIController(options) { + if (options === void 0) { + options = {}; + } + + _defineProperty(this, "tagName", void 0); + + _defineProperty(this, "className", void 0); + + _defineProperty(this, "el", void 0); + + _defineProperty(this, "_id", void 0); + + options = extend_default()({ + tagName: 'div' + }, options); + this.tagName = options.tagName; + this.className = options.className; + this._id = makeUIInstanceId(); + this.customEventManager = new customEvents_default.a(); + + this._setRootElement(options.rootElement); + } + /** + * @param {string|object} aType - event name and selector string + * @param {function} aFn - event handler + */ + + + var _proto = UIController.prototype; + + _proto.on = function on(aType, aFn) { + var _this = this; + + if (isObject_default()(aType)) { + forEachOwnProperties_default()(aType, function (fn, type) { + _this._addEvent(type, fn); + }); + } else { + this._addEvent(aType, aFn); + } + }; + + _proto._bindDomEvent = function _bindDomEvent(event, selector, fn) { + if (selector) { + dom["a" /* default */].findAll(this.el, selector).forEach(function (el) { + on_default()(el, event, fn); + }); + } else { + on_default()(this.el, event, fn); + } + } + /** + * bind event + * @param {string} type - event name and selector + * @param {function} fn - handler function + * @private + */ + ; + + _proto._addEvent = function _addEvent(type, fn) { + var _this$_parseEventType = this._parseEventType(type), + event = _this$_parseEventType.event, + selector = _this$_parseEventType.selector; + + if (inArray_default()(event, DOM_EVENTS) > -1) { + this._bindDomEvent(event, selector, fn); + } else { + this.customEventManager.on(event, fn); + } + }; + + _proto._unbindDomEvent = function _unbindDomEvent(event, selector, fn) { + if (selector) { + dom["a" /* default */].findAll(this.el, selector).forEach(function (el) { + off_default()(el, event, fn); + }); + } else { + off_default()(this.el, event, fn); + } + } + /** + * unbind event handler + * @param {string} type - event name and selector + * @param {function} fn - handler function + */ + ; + + _proto.off = function off(type, fn) { + var _this$_parseEventType2 = this._parseEventType(type), + event = _this$_parseEventType2.event, + selector = _this$_parseEventType2.selector; + + if (inArray_default()(event, DOM_EVENTS) > -1) { + this._unbindDomEvent(event, selector, fn); + } else { + this.customEventManager.off(event, fn); + } + } + /** + * parse string into event name & selector + * 'click td' => ['click', 'td'] + * @param {string} type - string to be parsed + * @returns {Object} event, selector + * @private + */ + ; + + _proto._parseEventType = function _parseEventType(type) { + var splitType = type.split(' '); + var event = splitType.shift(); + var selector = splitType.join(' '); + return { + event: event, + selector: selector + }; + } + /** + * set root element + * @param {HTMLElement} el - root element + * @private + */ + ; + + _proto._setRootElement = function _setRootElement(el) { + if (!el) { + var tagName = this.tagName; + el = document.createElement(tagName); + el.className = this.className || "uic" + this._id; + } + + this.el = el; + } + /** + * trigger event + * @param {string} eventName - event name + * @param {*} eventData - event data + */ + ; + + _proto.trigger = function trigger(eventName, eventData) { + this.customEventManager.fire(eventName, eventData); + } + /** + * remove + */ + ; + + _proto.remove = function remove() { + if (this.el) { + dom["a" /* default */].remove(this.el); + } + } + /** + * destroy + */ + ; + + _proto.destroy = function destroy() { + var _this2 = this; + + this.remove(); + forEachOwnProperties_default()(this, function (value, key) { + _this2[key] = null; + }); + }; + + return UIController; +}(); + +/* harmony default export */ var uicontroller = (uicontroller_UIController); +// CONCATENATED MODULE: ./src/js/ui/toolbarItem.js +function toolbarItem_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +function toolbarItem_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview Implements Toolbar Item + * @author NHN FE Development Lab + */ + + +/** + * Class ToolbarItem + * @param {Object} [options={name: 'toolbar-item'}] [description] + */ + +var toolbarItem_ToolbarItem = /*#__PURE__*/function (_UIController) { + toolbarItem_inheritsLoose(ToolbarItem, _UIController); + + /** + * item name + * @type {String} + * @static + * @private + */ + + /** + * toolbar item class name + * @type {String} + * @static + * @private + */ + function ToolbarItem(options) { + var _this; + + if (options === void 0) { + options = { + name: ToolbarItem.name + }; + } + + _this = _UIController.call(this, extend_default()({ + className: ToolbarItem.className + }, options)) || this; + _this._name = options.name; + return _this; + } + /** + * get the name of the toolbar item + * @returns {string} - the name of the toolbar item + */ + + + var _proto = ToolbarItem.prototype; + + _proto.getName = function getName() { + return this._name; + }; + + return ToolbarItem; +}(uicontroller); + +toolbarItem_defineProperty(toolbarItem_ToolbarItem, "name", 'item'); + +toolbarItem_defineProperty(toolbarItem_ToolbarItem, "className", 'tui-toolbar-item'); + +/* harmony default export */ var ui_toolbarItem = (toolbarItem_ToolbarItem); +// CONCATENATED MODULE: ./src/js/ui/tooltip.js +/** + * @fileoverview Implements tooltip + * @author NHN FE Development Lab + */ + + +var TOOLTIP_CONTENT = '
    '; +var TOOLTIP_TOP_INDENT = 7; +/** + * Class Tooltip + * @ignore + */ + +var tooltip_Tooltip = /*#__PURE__*/function () { + function Tooltip() { + this.el = dom["a" /* default */].createElementWith("
    " + TOOLTIP_CONTENT + "
    "); + document.body.appendChild(this.el); + this.hide(); + } + /** + * show tooltop + * @param {HTMLElement} target - target element to bind + * @param {String} text - text to show + */ + + + var _proto = Tooltip.prototype; + + _proto.show = function show(target, text) { + var targetRect = target.getBoundingClientRect(); + var left = targetRect.left + window.pageXOffset; + var top = targetRect.top + window.pageYOffset; + css_default()(this.el, { + top: top + target.clientHeight + TOOLTIP_TOP_INDENT + "px", + left: left + 3 + "px" + }); + this.el.querySelector('.text').innerHTML = text; + css_default()(this.el, { + display: 'block' + }); + }; + + _proto.hide = function hide() { + css_default()(this.el, { + display: 'none' + }); + }; + + _proto.remove = function remove() { + dom["a" /* default */].remove(this.el); + }; + + return Tooltip; +}(); + +/* harmony default export */ var tooltip = (new tooltip_Tooltip()); +// CONCATENATED MODULE: ./src/js/ui/toolbarButton.js +function toolbarButton_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function toolbarButton_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +function toolbarButton_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview Implements UI ToolbarButton + * @author NHN FE Development Lab + */ + + +/** + * @typedef {object} toolbarItemsValue + * @property {string} type - type of toolbar item (default value is 'button') + * @property {toolbarButtonOptions} options - options of toolbar item + */ + +/** + * @typedef {object} toolbarButtonOptions + * @property {HTMLElement} el - target element + * @property {string} className - button's class name + * @property {string} command - command name to execute on click + * @property {string} event - event name to trigger on click + * @property {string} text - text on button + * @property {string} tooltip - text on tooltip + * @property {string} style - button's style + * @property {string} state - button's state + */ + +/** + * Class ToolbarButton UI + * @param {toolbarButtonOptions} options - button options + * @ignore + */ + +var toolbarButton_ToolbarButton = /*#__PURE__*/function (_ToolbarItem) { + toolbarButton_inheritsLoose(ToolbarButton, _ToolbarItem); + + /** + * item name + * @type {String} + * @static + */ + + /** + * ToolbarItem className + * @type {String} + * @static + */ + function ToolbarButton(options) { + var _this; + + if (options === void 0) { + options = { + tagName: 'button', + name: ToolbarButton.name + }; + } + + _this = _ToolbarItem.call(this, { + name: options.name, + tagName: 'button', + className: options.className + " " + ToolbarButton.className, + rootElement: options.el + }) || this; + + _this._setOptions(options); + + _this._render(); + + _this.on('click', _this._onClick.bind(toolbarButton_assertThisInitialized(_this))); + + if (options.tooltip) { + _this.on('mouseover', _this._onOver.bind(toolbarButton_assertThisInitialized(_this))); + + _this.on('mouseout', _this._onOut.bind(toolbarButton_assertThisInitialized(_this))); + } + + return _this; + } + /** + * set tooltip text + * @param {string} text - tooltip text to show + */ + + + var _proto = ToolbarButton.prototype; + + _proto.setTooltip = function setTooltip(text) { + this._tooltip = text; + }; + + _proto._setOptions = function _setOptions(options) { + this._command = options.command; + this._event = options.event; + this._text = options.text; + this._tooltip = options.tooltip; + this._style = options.style; + this._state = options.state; + }; + + _proto._render = function _render() { + var text = document.createTextNode(this._text || ''); + this.el.appendChild(text); + this.el.setAttribute('type', 'button'); + + if (this._style) { + this.el.setAttribute('style', this._style); + } + }; + + _proto._onClick = function _onClick() { + if (!this.isEnabled()) { + return; + } + + if (this._command) { + this.trigger('command', this._command); + } else if (this._event) { + this.trigger('event', this._event); + } + + this.trigger('clicked'); + }; + + _proto._onOver = function _onOver() { + if (!this.isEnabled()) { + return; + } + + tooltip.show(this.el, this._tooltip); + }; + + _proto._onOut = function _onOut() { + tooltip.hide(); + } + /** + * enable button + */ + ; + + _proto.enable = function enable() { + this.el.disabled = false; + } + /** + * disable button + */ + ; + + _proto.disable = function disable() { + this.el.disabled = true; + } + /** + * check whether this button is enabled + * @returns {Boolean} - true for enabled + */ + ; + + _proto.isEnabled = function isEnabled() { + return !this.el.disabled; + }; + + return ToolbarButton; +}(ui_toolbarItem); + +toolbarButton_defineProperty(toolbarButton_ToolbarButton, "name", 'button'); + +toolbarButton_defineProperty(toolbarButton_ToolbarButton, "className", 'tui-toolbar-icons'); + +/* harmony default export */ var toolbarButton = (toolbarButton_ToolbarButton); +// CONCATENATED MODULE: ./src/js/ui/toolbarDivider.js +function toolbarDivider_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +function toolbarDivider_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview Implements Toolbar Divider + * @author NHN FE Development Lab + */ + +/** + * Class ToolbarDivider + * @ignore + */ + +var ToolbarDivider = /*#__PURE__*/function (_ToolbarItem) { + toolbarDivider_inheritsLoose(ToolbarDivider, _ToolbarItem); + + /** + * item name + * @type {String} + * @static + */ + + /** + * item class name + * @type {String} + * @static + */ + function ToolbarDivider() { + return _ToolbarItem.call(this, { + name: ToolbarDivider.name, + tagName: 'div', + className: ToolbarDivider.className + }) || this; + } + + return ToolbarDivider; +}(ui_toolbarItem); + +toolbarDivider_defineProperty(ToolbarDivider, "name", 'divider'); + +toolbarDivider_defineProperty(ToolbarDivider, "className", 'tui-toolbar-divider'); + +/* harmony default export */ var toolbarDivider = (ToolbarDivider); +// CONCATENATED MODULE: ./src/js/ui/toolbarItemFactory.js +/** + * @fileoverview Implements Toolbar Item Factory + * @author NHN FE Development Lab + */ + + + + +/** + * Toolbar Item Factory + * @ignore + */ + +var toolbarItemFactory_ToolbarItemFactory = /*#__PURE__*/function () { + function ToolbarItemFactory() {} + + /** + * create toolbar item instance + * @param {string} name - toolbar item name + * @param {object} [options] - options to the constructor + * @return {ToolbarItem} - created toolbar item instance + * @static + */ + + /* eslint-disable complexity */ + ToolbarItemFactory.create = function create(name, options) { + var toolbarItem; + + switch (name) { + case 'heading': + toolbarItem = new toolbarButton({ + name: 'heading', + className: 'tui-heading', + event: 'openHeadingSelect', + tooltip: i18n.get('Headings'), + state: 'heading' + }); + break; + + case 'bold': + toolbarItem = new toolbarButton({ + name: 'bold', + className: 'tui-bold', + command: 'Bold', + tooltip: i18n.get('Bold'), + state: 'strong' + }); + break; + + case 'italic': + toolbarItem = new toolbarButton({ + name: 'italic', + className: 'tui-italic', + command: 'Italic', + tooltip: i18n.get('Italic'), + state: 'emph' + }); + break; + + case 'strike': + toolbarItem = new toolbarButton({ + name: 'strike', + className: 'tui-strike', + command: 'Strike', + tooltip: i18n.get('Strike'), + state: 'strike' + }); + break; + + case 'hr': + toolbarItem = new toolbarButton({ + name: 'hr', + className: 'tui-hrline', + command: 'HR', + tooltip: i18n.get('Line'), + state: 'thematicBreak' + }); + break; + + case 'quote': + toolbarItem = new toolbarButton({ + name: 'quote', + className: 'tui-quote', + command: 'Blockquote', + tooltip: i18n.get('Blockquote'), + state: 'blockQuote' + }); + break; + + case 'ul': + toolbarItem = new toolbarButton({ + name: 'ul', + className: 'tui-ul', + command: 'UL', + tooltip: i18n.get('Unordered list'), + state: 'list' + }); + break; + + case 'ol': + toolbarItem = new toolbarButton({ + name: 'ol', + className: 'tui-ol', + command: 'OL', + tooltip: i18n.get('Ordered list'), + state: 'orderedList' + }); + break; + + case 'task': + toolbarItem = new toolbarButton({ + name: 'task', + className: 'tui-task', + command: 'Task', + tooltip: i18n.get('Task'), + state: 'taskList' + }); + break; + + case 'table': + toolbarItem = new toolbarButton({ + name: 'table', + className: 'tui-table', + event: 'openPopupAddTable', + tooltip: i18n.get('Insert table'), + state: 'table' + }); + break; + + case 'image': + toolbarItem = new toolbarButton({ + name: 'image', + className: 'tui-image', + event: 'openPopupAddImage', + tooltip: i18n.get('Insert image'), + state: '' + }); + break; + + case 'link': + toolbarItem = new toolbarButton({ + name: 'link', + className: 'tui-link', + event: 'openPopupAddLink', + tooltip: i18n.get('Insert link') + }); + break; + + case 'code': + toolbarItem = new toolbarButton({ + name: 'code', + className: 'tui-code', + command: 'Code', + tooltip: i18n.get('Code'), + state: 'code' + }); + break; + + case 'codeblock': + toolbarItem = new toolbarButton({ + name: 'codeblock', + className: 'tui-codeblock', + command: 'CodeBlock', + tooltip: i18n.get('Insert CodeBlock'), + state: 'codeBlock' + }); + break; + + case 'indent': + toolbarItem = new toolbarButton({ + name: 'indent', + className: 'tui-indent', + command: 'Indent', + tooltip: i18n.get('Indent') + }); + break; + + case 'outdent': + toolbarItem = new toolbarButton({ + name: 'outdent', + className: 'tui-outdent', + command: 'Outdent', + tooltip: i18n.get('Outdent') + }); + break; + + case 'divider': + toolbarItem = new toolbarDivider(); + break; + + case 'button': + toolbarItem = new toolbarButton(options); + break; + + case 'item': + default: + toolbarItem = new ui_toolbarItem(options); + } + + return toolbarItem; + } + /* eslint-enable complexity */ + ; + + return ToolbarItemFactory; +}(); + +/* harmony default export */ var toolbarItemFactory = (toolbarItemFactory_ToolbarItemFactory); +// CONCATENATED MODULE: ./src/js/ui/toolbar.js +function toolbar_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function toolbar_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +function toolbar_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview Implements toolbar + * @author NHN FE Development Lab + */ + + + + + + +/** + * Class Toolbar + * @param {EventManager} eventManager - event manager + * @param {ToolbarItem[]} [items=[]] - toolbar items + */ + +var toolbar_Toolbar = /*#__PURE__*/function (_UIController) { + toolbar_inheritsLoose(Toolbar, _UIController); + + /** + * items + * @type {Array} + * @private + */ + + /** + * event manager + * @type {EventManager} + * @private + */ + function Toolbar(eventManager, items) { + var _this; + + if (items === void 0) { + items = []; + } + + _this = _UIController.call(this, { + tagName: 'div', + className: 'tui-editor-defaultUI-toolbar' + }) || this; + + toolbar_defineProperty(toolbar_assertThisInitialized(_this), "_items", []); + + toolbar_defineProperty(toolbar_assertThisInitialized(_this), "_eventManager", void 0); + + _this._eventManager = eventManager; + + _this.setItems(items); + + _this._initEvent(eventManager); + + return _this; + } + /** + * init event + * @param {EventManager} eventManager - event manager + * @private + * @override + */ + + + var _proto = Toolbar.prototype; + + _proto._initEvent = function _initEvent(eventManager) { + var _this2 = this; + + eventManager.listen('stateChange', function (ev) { + _this2._items.forEach(function (item) { + if (item._state) { + dom["a" /* default */].toggleClass(item.el, 'active', !!ev[item._state]); + } + }); + }); + eventManager.listen('changePreviewTabPreview', function () { + return _this2.disableAllButton(); + }); + eventManager.listen('changePreviewTabWrite', function () { + return _this2.enableAllButton(); + }); + eventManager.listen('changeMode', function () { + return _this2.enableAllButton(); + }); + } + /** + * disable all toolbar button + */ + ; + + _proto.disableAllButton = function disableAllButton() { + this._items.forEach(function (item) { + if (item instanceof toolbarButton) { + item.disable(); + } + }); + } + /** + * enable all toolbar button + */ + ; + + _proto.enableAllButton = function enableAllButton() { + this._items.forEach(function (item) { + if (item instanceof toolbarButton) { + item.enable(); + } + }); + } + /** + * get toolbar items + * @returns {ToolbarItem[]} - toolbar items + */ + ; + + _proto.getItems = function getItems() { + return this._items.slice(0); + } + /** + * get toolbar item at given index + * @param {number} index - item index + * @returns {ToolbarItem} - toolbar item at the index + */ + ; + + _proto.getItem = function getItem(index) { + return this._items[index]; + } + /** + * set toolbar items + * @param {ToolbarItem[]} items - toolbar items + */ + ; + + _proto.setItems = function setItems(items) { + this.removeAllItems(); + items.forEach(this.addItem.bind(this)); + } + /** + * add toolbar item + * @param {ToolbarItem|string|object} item - toolbar item + */ + ; + + _proto.addItem = function addItem(item) { + this.insertItem(this._items.length, item); + } + /** + * insert toolbar item + * @param {number} index - index at given item inserted + * @param {ToolbarItem|string|object} item - toolbar item + */ + ; + + _proto.insertItem = function insertItem(index, item) { + var _this3 = this; + + if (isString_default()(item)) { + item = toolbarItemFactory.create(item); + } else if (isString_default()(item.type)) { + item = toolbarItemFactory.create(item.type, item.options); + } + + var children = this.el.children; + + if (index >= 0 && index < children.length) { + dom["a" /* default */].insertBefore(item.el, children[index]); + + this._items.splice(index, 0, item); + } else { + this.el.appendChild(item.el); + + this._items.push(item); + } + + item.onCommandHandler = function (commandName) { + return _this3._eventManager.emit('command', commandName); + }; + + item.onEventHandler = function (eventName) { + return _this3._eventManager.emit(eventName); + }; + + item.on('command', item.onCommandHandler); + item.on('event', item.onEventHandler); + } + /** + * get index of given item + * @param {ToolbarItem} item - toolbar item + * @returns {number} - index of given toolbar item + */ + ; + + _proto.indexOfItem = function indexOfItem(item) { + var index; + + if (item instanceof ui_toolbarItem) { + index = this._items.indexOf(item); + } else if (isString_default()(item)) { + var itemName = item; + index = this._items.map(function (itemToTest) { + return itemToTest.getName(); + }).indexOf(itemName); + } + + return index; + } + /** + * remove an item + * @param {ToolbarItem|number} item - an toolbar item or index of the item to remove + * @param {boolean} destroy - destroy item or not + * @returns {ToolbarItem|undefined} - removed item + */ + ; + + _proto.removeItem = function removeItem(item, destroy) { + if (destroy === void 0) { + destroy = true; + } + + var index; + var removedItem; + + if (item instanceof ui_toolbarItem) { + index = this.indexOfItem(item); + } else { + index = item; + } + + if (index >= 0) { + removedItem = this._items.splice(index, 1)[0]; + } + + if (removedItem) { + if (destroy) { + removedItem.destroy(); + } else { + removedItem.off('command', removedItem.onCommandHandler); + removedItem.off('event', removedItem.onEventHandler); + dom["a" /* default */].remove(removedItem.el); + } + } + + return removedItem; + } + /** + * remove all toolbar items + */ + ; + + _proto.removeAllItems = function removeAllItems() { + while (this._items && this._items.length > 0) { + this.removeItem(0); + } + } + /** + * destroy instance + * @override + */ + ; + + _proto.destroy = function destroy() { + this.removeAllItems(); + + _UIController.prototype.destroy.call(this); + }; + + return Toolbar; +}(uicontroller); + +/* harmony default export */ var ui_toolbar = (toolbar_Toolbar); +// CONCATENATED MODULE: ./src/js/ui/layerpopup.js +function layerpopup_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function layerpopup_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements LayerPopup + * @author NHN FE Development Lab + */ + + + + + + + + + + +var CLASS_PREFIX = 'tui-popup-'; +var CLASS_FIT_WINDOW = 'fit-window'; +var LAYOUT_TEMPLATE_MODELESS = "
    \n \n
    \n \n
    \n
    \n
    "; +var LAYOUT_TEMPLATE_MODAL = "
    \n
    \n \n
    \n \n
    \n
    \n
    \n
    "; +/** + * A number, or a string containing a number. + * @typedef {object} LayerPopupOption + * @property {string[]} [openerCssQuery] - Css Query list to bind clickevent that open popup + * @property {string[]} [closerCssQuery] - Css Query list to bind clickevent that close popup + * @property {HTMLElement} el - popup root element + * @property {HTMLElement|string} [content] - popup content that html string or element + * @property {string} [textContent] - popup text content + * @property {string} title - popup title + * @property {boolean} [header] - whether to draw header + * @property {HTMLElement} [target] - element to append popup + * @property {boolean} modal - true: modal, false: modeless + * @property {string} [headerButtons] - replace header(close) button + */ + +/** + * Class LayerPopup + * @param {LayerPopupOption} options - popup option + */ + +var layerpopup_LayerPopup = /*#__PURE__*/function (_UIController) { + layerpopup_inheritsLoose(LayerPopup, _UIController); + + function LayerPopup(options) { + var _this; + + options = extend_default()({ + header: true, + target: document.body, + textContent: '' + }, options); + _this = _UIController.call(this, { + tagName: 'div', + className: options.modal ? CLASS_PREFIX + "modal-background" : CLASS_PREFIX + "wrapper", + rootElement: options.el + }) || this; + _this._clickEventMap = {}; + _this._onClickCloseButton = _this.hide.bind(layerpopup_assertThisInitialized(_this)); + + _this._initInstance(options); + + _this._initDOM(options); + + _this._initDOMEvent(options); + + _this._initEditorEvent(options); + + return _this; + } + /** + * init instance. + * store properties & prepare before initialize DOM + * @param {LayerPopupOption} options - layer popup options + * @private + */ + + + var _proto = LayerPopup.prototype; + + _proto._initInstance = function _initInstance(options) { + this._target = options.target; + + if (options.el) { + this.el = options.el; + this._isExternalHtmlUse = true; + } + + if (options.content) { + this.content = options.content; + } else { + this.content = options.textContent; + } + + this.options = options; + } + /** + * initialize DOM, render popup + * @private + */ + ; + + _proto._initDOM = function _initDOM() { + this._initLayout(); + + if (!this._isExternalHtmlUse) { + if (isExisty_default()(this.options.title)) { + this.setTitle(this.options.title); + } + + this.setContent(this.content); + } + + var buttons = this.options.headerButtons; + + if (buttons) { + var closeButtons = dom["a" /* default */].findAll(this.el, "." + CLASS_PREFIX + "close-button"); + closeButtons.forEach(function (button) { + dom["a" /* default */].remove(button); + }); + var buttonWrapper = this.el.querySelector("." + CLASS_PREFIX + "header-buttons"); + dom["a" /* default */].empty(buttonWrapper); + buttonWrapper.innerHTML = buttons; + } + + if (this.options.css) { + css_default()(this.el, this.options.css); + } + } + /** + * bind DOM events + * @private + */ + ; + + _proto._initDOMEvent = function _initDOMEvent() { + var _this2 = this; + + var _this$options = this.options, + openerCssQuery = _this$options.openerCssQuery, + closerCssQuery = _this$options.closerCssQuery; + var _document = document, + body = _document.body; + + if (openerCssQuery) { + dom["a" /* default */].findAll(body, openerCssQuery).forEach(function (el) { + var eventKey = "click." + _this2._id; + _this2._clickEventMap[eventKey] = _this2.show.bind(_this2); + on_default()(el, 'click', _this2._clickEventMap[eventKey]); + }); + } + + if (closerCssQuery) { + dom["a" /* default */].findAll(body, closerCssQuery).forEach(function (el) { + var eventKey = "click." + _this2._id; + _this2._clickEventMap[eventKey] = _this2.hide.bind(_this2); + on_default()(el, 'click', _this2._clickEventMap[eventKey]); + }); + } + + this.on("click ." + CLASS_PREFIX + "close-button", this._onClickCloseButton); + } + /** + * bind editor events + * @private + * @abstract + */ + ; + + _proto._initEditorEvent = function _initEditorEvent() {}; + + _proto._initLayout = function _initLayout() { + var options = this.options; + + if (!this._isExternalHtmlUse) { + var layout = options.modal ? LAYOUT_TEMPLATE_MODAL : LAYOUT_TEMPLATE_MODELESS; + this.el.innerHTML = layout; + + if (options.className) { + addClass_default.a.apply(void 0, [this.el].concat(options.className.split(/\s+/g))); + } + + this.hide(); + + this._target.appendChild(this.el); + + this.body = this.el.querySelector("." + CLASS_PREFIX + "body"); + + if (!options.header) { + dom["a" /* default */].remove(this.el.querySelector("." + CLASS_PREFIX + "header")); + } + } else { + this.hide(); + + this._target.appendChild(this.el); + } + } + /** + * set popup content + * @param {HTMLElement|string} content - content + */ + ; + + _proto.setContent = function setContent(content) { + dom["a" /* default */].empty(this.body); + + if (isString_default()(content)) { + this.body.innerHTML = content; + } else { + this.body.appendChild(content); + } + } + /** + * set title + * @param {string} title - title text + */ + ; + + _proto.setTitle = function setTitle(title) { + var titleWrapper = this.el.querySelector("." + CLASS_PREFIX + "title"); + dom["a" /* default */].empty(titleWrapper); + titleWrapper.innerHTML = title; + } + /** + * get title element + * @returns {HTMLElement} - title html element + */ + ; + + _proto.getTitleElement = function getTitleElement() { + return this.el.querySelector("." + CLASS_PREFIX + "title"); + } + /** + * hide popup + */ + ; + + _proto.hide = function hide() { + css_default()(this.el, { + display: 'none' + }); + this._isShow = false; + this.trigger('hidden', this); + } + /** + * show popup + */ + ; + + _proto.show = function show() { + css_default()(this.el, { + display: 'block' + }); + this._isShow = true; + this.trigger('shown', this); + } + /** + * whether this popup is visible + * @returns {boolean} - true: shown, false: hidden + */ + ; + + _proto.isShow = function isShow() { + return this._isShow; + } + /** + * remove popup content + */ + ; + + _proto.remove = function remove() { + var _this3 = this; + + var _this$options2 = this.options, + openerCssQuery = _this$options2.openerCssQuery, + closerCssQuery = _this$options2.closerCssQuery; + var _document2 = document, + body = _document2.body; + this.trigger('remove', this); + this.off("click ." + CLASS_PREFIX + "close-button", this._onClickCloseButton); + + if (openerCssQuery) { + dom["a" /* default */].findAll(body, openerCssQuery).forEach(function (opener) { + off_default()(opener, 'click', _this3._clickEventMap["click." + _this3._id]); + delete _this3._clickEventMap["click." + _this3._id]; + }); + } + + if (closerCssQuery) { + dom["a" /* default */].findAll(body, closerCssQuery).forEach(function (closer) { + off_default()(closer, 'click', _this3._clickEventMap["click." + _this3._id]); + delete _this3._clickEventMap["click." + _this3._id]; + }); + } + + dom["a" /* default */].remove(this.el); + this.el = null; + } + /** + * make popup size fit to window + * @param {boolean} fit - true to make popup fit to window + * @protected + * @ignore + */ + ; + + _proto.setFitToWindow = function setFitToWindow(fit) { + dom["a" /* default */].toggleClass(this.el, CLASS_FIT_WINDOW, fit); + } + /** + * make popup size fit to window + * @returns {boolean} - true for fit to window + * @protected + * @ignore + */ + ; + + _proto.isFitToWindow = function isFitToWindow() { + return hasClass_default()(this.el, CLASS_FIT_WINDOW); + } + /** + * toggle size fit to window + * @returns {boolean} - true for fit to window + * @protected + * @ignore + */ + ; + + _proto.toggleFitToWindow = function toggleFitToWindow() { + var fitToWindow = !this.isFitToWindow(); + this.setFitToWindow(fitToWindow); + return fitToWindow; + }; + + return LayerPopup; +}(uicontroller); + +/* harmony default export */ var layerpopup = (layerpopup_LayerPopup); +// CONCATENATED MODULE: ./src/js/ui/popupDropdownToolbar.js +function popupDropdownToolbar_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +function popupDropdownToolbar_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview implements DefaultToolbar + * @author NHN FE Development Lab + */ + + + + + +/** + * Class PopupDropdownToolbar + * @param {LayerPopupOption} options - layer popup option + * @ignore + */ + +var popupDropdownToolbar_PopupDropdownToolbar = /*#__PURE__*/function (_LayerPopup) { + popupDropdownToolbar_inheritsLoose(PopupDropdownToolbar, _LayerPopup); + + /** + * open event string + * @type {string} + */ + function PopupDropdownToolbar(options) { + options = extend_default()({ + header: false, + className: 'te-dropdown-toolbar' + }, options); + return _LayerPopup.call(this, options) || this; + } + /** + * get toolbar instance it contains + * @returns {Toolbar} - toolbar instance + */ + + + var _proto = PopupDropdownToolbar.prototype; + + _proto.getToolbar = function getToolbar() { + return this._toolbar; + } + /** + * get toolbar items + * @returns {ToolbarItem[]} - toolbar items + */ + ; + + _proto.getItems = function getItems() { + return this.getToolbar().getItems(); + } + /** + * get toolbar item at given index + * @param {number} index - item index + * @returns {ToolbarItem} - toolbar item at the index + */ + ; + + _proto.getItem = function getItem(index) { + return this.getToolbar().getItem(index); + } + /** + * set toolbar items + * @param {ToolbarItem[]} items - toolbar items + */ + ; + + _proto.setItems = function setItems(items) { + this.getToolbar().setItems(items); + } + /** + * add toolbar item + * @param {ToolbarItem|string|object} item - toolbar item + */ + ; + + _proto.addItem = function addItem(item) { + this.getToolbar().addItem(item); + } + /** + * insert toolbar item + * @param {number} index - index at given item inserted + * @param {ToolbarItem|string|object} item - toolbar item + */ + ; + + _proto.insertItem = function insertItem(index, item) { + this.getToolbar().insertItem(index, item); + } + /** + * get index of given item + * @param {ToolbarItem} item - toolbar item + * @returns {number} - index of given toolbar item + */ + ; + + _proto.indexOfItem = function indexOfItem(item) { + return this.getToolbar().indexOfItem(item); + } + /** + * remove an item + * @param {number} index - item index to remove + * @param {boolean} destroy - destroy item or not + * @returns {ToolbarItem} - removed item + */ + ; + + _proto.removeItem = function removeItem(index, destroy) { + return this.getToolbar().removeItem(index, destroy); + } + /** + * remove all toolbar items + */ + ; + + _proto.removeAllItems = function removeAllItems() { + this.getToolbar().removeAllItems(); + } + /** + * init instance. + * store properties & prepare before initialize DOM + * @param {LayerPopupOption} options - layer popup options + * @private + * @override + */ + ; + + _proto._initInstance = function _initInstance(options) { + _LayerPopup.prototype._initInstance.call(this, options); + + var button = options.button, + eventManager = options.eventManager; + this._button = button; + this._eventManager = eventManager; + this._toolbar = new ui_toolbar(eventManager); + } + /** + * initialize DOM, render popup + * @private + * @override + */ + ; + + _proto._initDOM = function _initDOM() { + _LayerPopup.prototype._initDOM.call(this); + + this.setContent(this._toolbar.el); + } + /** + * bind editor events + * @private + * @override + */ + ; + + _proto._initEditorEvent = function _initEditorEvent() { + var _this = this; + + _LayerPopup.prototype._initEditorEvent.call(this); + + this._eventManager.listen('focus', function () { + return _this.hide(); + }); + + this._eventManager.listen('closeAllPopup', function () { + return _this.hide(); + }); + + this._eventManager.listen(PopupDropdownToolbar.OPEN_EVENT, function () { + var isShown = _this.isShow(); + + _this._eventManager.emit('closeAllPopup'); + + if (!isShown) { + _this.show(); + } // to give toolbar element enough width before the calculation + + + css_default()(_this.el, { + left: '-1000px' + }); + var button = _this._button; + var buttonOuterHeightWithMargin = dom["a" /* default */].getOuterHeight(button, true); + var buttonMarginBottom = (buttonOuterHeightWithMargin - dom["a" /* default */].getOuterHeight(button)) / 2; + var top = button.offsetTop + buttonOuterHeightWithMargin - buttonMarginBottom; + var left = button.offsetLeft + dom["a" /* default */].getOuterWidth(button, true) - dom["a" /* default */].getOuterWidth(_this.el, true); + css_default()(_this.el, { + top: top + "px", + left: left + "px" + }); + }); + }; + + return PopupDropdownToolbar; +}(layerpopup); + +popupDropdownToolbar_defineProperty(popupDropdownToolbar_PopupDropdownToolbar, "OPEN_EVENT", 'openDropdownToolbar'); + +/* harmony default export */ var popupDropdownToolbar = (popupDropdownToolbar_PopupDropdownToolbar); +// CONCATENATED MODULE: ./src/js/ui/defaultToolbar.js +function defaultToolbar_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function defaultToolbar_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +function defaultToolbar_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview implements DefaultToolbar + * @author NHN FE Development Lab + */ + + + + + +var MORE_BUTTON_NAME = 'more'; +/** + * Class DefaultToolbar + */ + +var defaultToolbar_DefaultToolbar = /*#__PURE__*/function (_Toolbar) { + defaultToolbar_inheritsLoose(DefaultToolbar, _Toolbar); + + /** + * more button + * @type {ToolbarButton} + * @private + */ + + /** + * popup dropdown toolbar + * @type {PopupDropdownToolbar} + * @private + */ + + /** + * resize observer + * @type {ResizeObserver} + * @private + */ + function DefaultToolbar(eventManager, options) { + var _this; + + _this = _Toolbar.call(this, eventManager, options) || this; + + defaultToolbar_defineProperty(defaultToolbar_assertThisInitialized(_this), "_moreButton", void 0); + + defaultToolbar_defineProperty(defaultToolbar_assertThisInitialized(_this), "_popupDropdownToolbar", void 0); + + defaultToolbar_defineProperty(defaultToolbar_assertThisInitialized(_this), "_observer", void 0); + + _this._init(eventManager); + + _this._bindWidthChangedEvent(); + + return _this; + } + /** + * insert toolbar item + * @param {number} index - index at given item inserted + * @param {ToolbarItem|string|object} item - toolbar item + * @override + */ + + + var _proto = DefaultToolbar.prototype; + + _proto.insertItem = function insertItem(index, item) { + _Toolbar.prototype.insertItem.call(this, index, item); + + this._arrangeMoreButton(); + }; + + _proto._init = function _init(eventManager) { + var moreButton = toolbarItemFactory.create('button', { + name: MORE_BUTTON_NAME, + className: 'tui-more', + tooltip: i18n.get('More'), + event: popupDropdownToolbar.OPEN_EVENT + }); + this._moreButton = moreButton; + this._popupDropdownToolbar = new popupDropdownToolbar({ + eventManager: eventManager, + target: this.el, + button: moreButton.el + }); + this.addItem(moreButton); + }; + + _proto._bindWidthChangedEvent = function _bindWidthChangedEvent() { + var _this2 = this; + + this._observer = new ResizeObserver_es["a" /* default */](function () { + _this2._popupDropdownToolbar.hide(); + + _this2._balanceButtons(); + }); + + this._observer.observe(this.el); + }; + + _proto._balanceButtons = function _balanceButtons() { + var _this3 = this; + + var dropDownToolbarItems = this._popupDropdownToolbar.getItems(); + + dropDownToolbarItems.forEach(function (item) { + _this3._popupDropdownToolbar.removeItem(item, false); + + var itemLength = _this3.getItems().length; + + _Toolbar.prototype.insertItem.call(_this3, itemLength, item); + }); + this.removeItem(this._moreButton, false); + + _Toolbar.prototype.insertItem.call(this, 0, this._moreButton); + + var defaultToolbarItems = this.getItems(); + var overflowItems = defaultToolbarItems.filter(function (item) { + return item.el.offsetTop > _this3.el.clientHeight; + }); + overflowItems.forEach(function (item) { + _this3.removeItem(item, false); + + _this3._popupDropdownToolbar.addItem(item); + }); + + this._arrangeMoreButton(); + }; + + _proto._arrangeMoreButton = function _arrangeMoreButton() { + if (!this._popupDropdownToolbar) { + return; + } + + this.removeItem(this._moreButton, false); + var hasOverflow = this._popupDropdownToolbar.getItems().length > 0; + var itemLength = this.getItems().length; + + if (hasOverflow) { + _Toolbar.prototype.insertItem.call(this, itemLength, this._moreButton); + } + } + /** + * destroy + * @override + */ + ; + + _proto.destroy = function destroy() { + if (this._observer) { + this._observer.disconnect(); + + this._observer = null; + } + }; + + return DefaultToolbar; +}(ui_toolbar); + +/* harmony default export */ var defaultToolbar = (defaultToolbar_DefaultToolbar); +// CONCATENATED MODULE: ./src/js/ui/tab.js +function tab_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements tab button ui + * @author NHN FE Development Lab + */ + + + + +var CLASS_TAB_ACTIVE = 'te-tab-active'; +/** + * Class Tab + * @param {object} options - options + * @param {string} [options.initName] - name of the default activated button + * @param {string[]} options.items - button names to be created + * @param {DOMElement[]} options.sections - dom elements for tab + * @param {function} [options.onItemClick] - when button is clicked pass button name to function + * @ignore + */ + +var tab_Tab = /*#__PURE__*/function (_UIController) { + tab_inheritsLoose(Tab, _UIController); + + function Tab(options) { + var _this; + + if (options === void 0) { + options = {}; + } + + _this = _UIController.call(this, { + tagName: 'div', + className: 'te-tab' + }) || this; + _this.sections = options.sections; + _this._activeButton = null; + + _this._render(options); + + _this._initEvent(options); + + return _this; + } + + var _proto = Tab.prototype; + + _proto._initEvent = function _initEvent(options) { + var onItemClick = options.onItemClick; + + if (onItemClick) { + this.on('itemClick', onItemClick); + } + + this.on('click button', this._onTabButton.bind(this)); + }; + + _proto._render = function _render(options) { + var items = options.items, + initName = options.initName; + var tabButtons = []; + + for (var i = 0, len = items.length; i < len; i += 1) { + tabButtons.push(""); + } + + this.el.innerHTML = tabButtons.join(''); + this.activate(initName); + }; + + _proto._findButtonContained = function _findButtonContained(element, selector, text) { + return dom["a" /* default */].findAll(element, selector).filter(function (node) { + return new RegExp(text).test(node.textContent); + }); + } + /** + * Activate section & button + * @param {string} name button name to activate + */ + ; + + _proto.activate = function activate(name) { + var _this$_findButtonCont = this._findButtonContained(this.el, 'button', name), + button = _this$_findButtonCont[0]; + + this._activateTabByButton(button); + }; + + _proto._onTabButton = function _onTabButton(ev) { + var button = ev.target; + + this._activateTabByButton(button); + + this.trigger('itemClick', button.textContent); + }; + + _proto._activateTabByButton = function _activateTabByButton(button) { + if (this._isActivatedButton(button)) { + return; + } + + this._updateClassByButton(button); + }; + + _proto._updateClassByButton = function _updateClassByButton(activeButton) { + // deactivate previously activated button + if (this._activeButton) { + var sectionIndex = this._activeButton.getAttribute('data-index'); + + removeClass_default()(this._activeButton, CLASS_TAB_ACTIVE); + + if (this.sections) { + removeClass_default()(this.sections[sectionIndex], CLASS_TAB_ACTIVE); + } + } // activate new button + + + addClass_default()(activeButton, CLASS_TAB_ACTIVE); + this._activeButton = activeButton; + var index = activeButton.getAttribute('data-index'); + + if (this.sections) { + addClass_default()(this.sections[index], CLASS_TAB_ACTIVE); + } + }; + + _proto._isActivatedButton = function _isActivatedButton(button) { + return this._activeButton && this._activeButton.textContent === button.textContent; + }; + + return Tab; +}(uicontroller); + +/* harmony default export */ var tab = (tab_Tab); +// CONCATENATED MODULE: ./src/js/ui/modeSwitch.js +function modeSwitch_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function modeSwitch_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +function modeSwitch_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview Implements ui mode switch + * @author NHN FE Development Lab + */ + + + + + + + +var MARKDOWN = 'markdown'; +var WYSIWYG = 'wysiwyg'; +/** + * Class ModeSwitch + * UI Control for switch between Markdown and WYSIWYG + * @param {HTMLElement} rootElement - root element + * @param {string} initialType - initial type of editor + */ + +var modeSwitch_ModeSwitch = /*#__PURE__*/function (_UIController) { + modeSwitch_inheritsLoose(ModeSwitch, _UIController); + + /** + * mode switch type + * @property {string} MARKDOWN - Markdown + * @property {string} WYSIWYG - WYSIWYG + * @static + * @ignore + */ + + /** + * mode switch buttons + * @type {Object} + * @private + */ + + /** + * current mode + * @type {String} + * @private + */ + + /** + * root element + * @type {HTMLElement} + * @private + */ + function ModeSwitch(rootElement, initialType, eventManager) { + var _this; + + _this = _UIController.call(this, { + tagName: 'div', + className: 'te-mode-switch' + }) || this; + + modeSwitch_defineProperty(modeSwitch_assertThisInitialized(_this), "_buttons", {}); + + modeSwitch_defineProperty(modeSwitch_assertThisInitialized(_this), "_type", void 0); + + modeSwitch_defineProperty(modeSwitch_assertThisInitialized(_this), "_rootElement", void 0); + + _this._eventManager = eventManager; + + _this._render(rootElement); + + _this._switchType(isExisty_default()(initialType) ? initialType : MARKDOWN); + + _this._initEvent(); + + return _this; + } + /** + * is the switch tab bar shown + * @returns {Boolean} - showing status + */ + + + var _proto = ModeSwitch.prototype; + + _proto.isShown = function isShown() { + return this._rootElement.style.display === 'block'; + } + /** + * show switch tab bar + */ + ; + + _proto.show = function show() { + css_default()(this._rootElement, { + display: 'block' + }); + } + /** + * hide switch tab bar + */ + ; + + _proto.hide = function hide() { + css_default()(this._rootElement, { + display: 'none' + }); + }; + + _proto._render = function _render(rootElement) { + this._buttons.markdown = dom["a" /* default */].createElementWith(""); + this._buttons.wysiwyg = dom["a" /* default */].createElementWith(""); + this.el.appendChild(this._buttons.markdown); + this.el.appendChild(this._buttons.wysiwyg); + + if (rootElement) { + rootElement.appendChild(this.el); + this._rootElement = rootElement; + } + + this.on('click .markdown', this._changeMarkdown.bind(this)); + this.on('click .wysiwyg', this._changeWysiwyg.bind(this)); + this.show(); + }; + + _proto._changeMarkdown = function _changeMarkdown() { + this._switchType(MARKDOWN); + }; + + _proto._changeWysiwyg = function _changeWysiwyg() { + this._switchType(WYSIWYG); + }; + + _proto._setActiveButton = function _setActiveButton(type) { + removeClass_default()(this._buttons.markdown, 'active'); + removeClass_default()(this._buttons.wysiwyg, 'active'); + addClass_default()(this._buttons["" + type], 'active'); + }; + + _proto._switchType = function _switchType(type) { + if (this._type === type) { + return; + } + + this._type = type; + + this._setActiveButton(type); + + this.trigger('modeSwitched', this._type); + }; + + _proto._initEvent = function _initEvent() { + var _this2 = this; + + this._eventManager.listen('changeMode', function (type) { + if (_this2._type !== type) { + _this2._type = type; + + _this2._setActiveButton(type); + } + }); + }; + + return ModeSwitch; +}(uicontroller); + +modeSwitch_defineProperty(modeSwitch_ModeSwitch, "TYPE", { + MARKDOWN: MARKDOWN, + WYSIWYG: WYSIWYG +}); + +/* harmony default export */ var ui_modeSwitch = (modeSwitch_ModeSwitch); +// CONCATENATED MODULE: ./src/js/ui/popupAddLink.js +function popupAddLink_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements PopupAddLink + * @author NHN FE Development Lab + */ + + + + + +var URL_REGEX = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})(\/([^\s]*))?$/; +/** + * Class PopupAddLink + * It implements a link Add Popup + * @param {LayerPopupOption} options - layer popup options + * @ignore + */ + +var popupAddLink_PopupAddLink = /*#__PURE__*/function (_LayerPopup) { + popupAddLink_inheritsLoose(PopupAddLink, _LayerPopup); + + function PopupAddLink(options) { + var _this; + + var POPUP_CONTENT = "\n \n \n \n \n
    \n \n \n
    \n "; + options = extend_default()({ + header: true, + title: i18n.get('Insert link'), + className: 'te-popup-add-link tui-editor-popup', + content: POPUP_CONTENT + }, options); + _this = _LayerPopup.call(this, options) || this; + _this._disabledLinkText = false; + return _this; + } + /** + * init instance. + * store properties & prepare before initialize DOM + * @param {LayerPopupOption} options - layer popup options + * @private + * @override + */ + + + var _proto = PopupAddLink.prototype; + + _proto._initInstance = function _initInstance(options) { + _LayerPopup.prototype._initInstance.call(this, options); + + this._editor = options.editor; + this._eventManager = options.editor.eventManager; + } + /** + * initialize DOM, render popup + * @private + * @override + */ + ; + + _proto._initDOM = function _initDOM() { + _LayerPopup.prototype._initDOM.call(this); + + var el = this.el; + this._inputText = el.querySelector('.te-link-text-input'); + this._inputURL = el.querySelector('.te-url-input'); + } + /** + * bind DOM events + * @private + * @override + */ + ; + + _proto._initDOMEvent = function _initDOMEvent() { + var _this2 = this; + + _LayerPopup.prototype._initDOMEvent.call(this); + + this.on('click .te-close-button', function () { + return _this2.hide(); + }); + this.on('click .te-ok-button', function () { + return _this2._addLink(); + }); + this.on('shown', function () { + _this2._disabledLinkText = _this2._editor.isWysiwygMode() && !_this2._editor.getRange().collapsed; + + _this2._disableLinkTextInput(); + + var inputText = _this2._inputText; + var inputURL = _this2._inputURL; + + var selectedText = _this2._editor.getSelectedText().trim(); + + inputText.value = selectedText; + + if (URL_REGEX.exec(selectedText)) { + inputURL.value = selectedText; + } + + inputURL.focus(); + }); + this.on('hidden', function () { + _this2._resetInputs(); + }); + } + /** + * bind editor events + * @private + * @override + */ + ; + + _proto._initEditorEvent = function _initEditorEvent() { + var _this3 = this; + + _LayerPopup.prototype._initEditorEvent.call(this); + + var eventManager = this._eventManager; + eventManager.listen('focus', function () { + return _this3.hide(); + }); + eventManager.listen('closeAllPopup', function () { + return _this3.hide(); + }); + eventManager.listen('openPopupAddLink', function (linkData) { + eventManager.emit('closeAllPopup'); + + if (linkData) { + _this3._inputURL.value = linkData.url; + } + + _this3.show(); + }); + }; + + _proto._disableLinkTextInput = function _disableLinkTextInput() { + var input = this._inputText; + + if (this._disabledLinkText) { + input.setAttribute('disabled', 'disabled'); + addClass_default()(input, 'disabled'); + } else { + input.removeAttribute('disabled'); + removeClass_default()(input, 'disabled'); + } + }; + + _proto._addLink = function _addLink() { + var _this$_getValue = this._getValue(), + url = _this$_getValue.url, + linkText = _this$_getValue.linkText; + + this._clearValidationStyle(); + + if (!this._disabledLinkText && linkText.length < 1) { + addClass_default()(this._inputText, 'wrong'); + return; + } + + if (url.length < 1) { + addClass_default()(this._inputURL, 'wrong'); + return; + } + + this._eventManager.emit('command', 'AddLink', { + linkText: linkText, + url: url + }); + + this.hide(); + }; + + _proto._getValue = function _getValue() { + var url = this._inputURL.value; + var linkText = this._inputText.value; + return { + url: url, + linkText: linkText + }; + }; + + _proto._clearValidationStyle = function _clearValidationStyle() { + removeClass_default()(this._inputURL, 'wrong', 'disabled'); + removeClass_default()(this._inputText, 'wrong'); + }; + + _proto._resetInputs = function _resetInputs() { + this._inputText.removeAttribute('disabled'); + + this._inputText.value = ''; + this._inputURL.value = ''; + + this._clearValidationStyle(); + }; + + return PopupAddLink; +}(layerpopup); + +/* harmony default export */ var popupAddLink = (popupAddLink_PopupAddLink); +// CONCATENATED MODULE: ./src/js/ui/popupAddImage.js +function popupAddImage_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements PopupAddImage + * @author NHN FE Development Lab + */ + + + + + +var CLASS_IMAGE_URL_INPUT = 'te-image-url-input'; +var CLASS_IMAGE_FILE_INPUT = 'te-image-file-input'; +var CLASS_ALT_TEXT_INPUT = 'te-alt-text-input'; +var CLASS_OK_BUTTON = 'te-ok-button'; +var CLASS_CLOSE_BUTTON = 'te-close-button'; +var CLASS_FILE_TYPE = 'te-file-type'; +var CLASS_URL_TYPE = 'te-url-type'; +var CLASS_TAB_SECTION = 'te-tab-section'; +var TYPE_UI = 'ui'; +/** + * Class PopupAddImage + * It implements a Image Add Popup + * @param {LayerPopupOption} options - layer popup option + * @ignore + */ + +var popupAddImage_PopupAddImage = /*#__PURE__*/function (_LayerPopup) { + popupAddImage_inheritsLoose(PopupAddImage, _LayerPopup); + + function PopupAddImage(options) { + var POPUP_CONTENT = "\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n \n \n
    \n \n \n
    \n "; + options = extend_default()({ + header: true, + title: i18n.get('Insert image'), + className: 'te-popup-add-image tui-editor-popup', + content: POPUP_CONTENT + }, options); + return _LayerPopup.call(this, options) || this; + } + /** + * init instance. + * store properties & prepare before initialize DOM + * @param {LayerPopupOption} options - layer popup options + * @private + * @override + */ + + + var _proto = PopupAddImage.prototype; + + _proto._initInstance = function _initInstance(options) { + _LayerPopup.prototype._initInstance.call(this, options); + + this.eventManager = options.eventManager; + } + /** + * initialize DOM, render popup + * @private + * @override + */ + ; + + _proto._initDOM = function _initDOM() { + _LayerPopup.prototype._initDOM.call(this); + + var popup = this.el; + this._imageUrlInput = popup.querySelector("." + CLASS_IMAGE_URL_INPUT); + this._imageFileInput = popup.querySelector("." + CLASS_IMAGE_FILE_INPUT); + this._altTextInput = popup.querySelector("." + CLASS_ALT_TEXT_INPUT); + var fileTypeSection = popup.querySelector("." + CLASS_FILE_TYPE); + var urlTypeSection = popup.querySelector("." + CLASS_URL_TYPE); + var tabSection = this.body.querySelector("." + CLASS_TAB_SECTION); + this.tab = new tab({ + initName: i18n.get('File'), + items: [i18n.get('File'), i18n.get('URL')], + sections: [fileTypeSection, urlTypeSection] + }); + tabSection.appendChild(this.tab.el); + } + /** + * bind DOM events + * @private + * @override + */ + ; + + _proto._initDOMEvent = function _initDOMEvent() { + var _this = this; + + _LayerPopup.prototype._initDOMEvent.call(this); + + this.on('shown', function () { + return _this._imageUrlInput.focus(); + }); + this.on('hidden', function () { + return _this._resetInputs(); + }); + this.on("change ." + CLASS_IMAGE_FILE_INPUT, function () { + var filename = _this._imageFileInput.value.split('\\').pop(); + + _this._altTextInput.value = filename; + }); + this.on("click ." + CLASS_CLOSE_BUTTON, function () { + return _this.hide(); + }); + this.on("click ." + CLASS_OK_BUTTON, function () { + var imageUrl = _this._imageUrlInput.value; + var altText = _this._altTextInput.value; + + if (imageUrl) { + _this._applyImage(imageUrl, altText); + } else { + var files = _this._imageFileInput.files; + + if (files.length) { + var imageFile = files.item(0); + + var hookCallback = function hookCallback(url, text) { + return _this._applyImage(url, text || altText); + }; + + _this.eventManager.emit('addImageBlobHook', imageFile, hookCallback, TYPE_UI); + } + } + + _this.hide(); + }); + this.tab.on('itemClick', function () { + return _this._resetInputs(); + }); + } + /** + * bind editor events + * @private + * @override + */ + ; + + _proto._initEditorEvent = function _initEditorEvent() { + var _this2 = this; + + _LayerPopup.prototype._initEditorEvent.call(this); + + this.eventManager.listen('focus', function () { + return _this2.hide(); + }); + this.eventManager.listen('closeAllPopup', function () { + return _this2.hide(); + }); + this.eventManager.listen('openPopupAddImage', function () { + _this2.eventManager.emit('closeAllPopup'); + + _this2.show(); + }); + }; + + _proto._applyImage = function _applyImage(imageUrl, altText) { + this.eventManager.emit('command', 'AddImage', { + imageUrl: imageUrl, + altText: altText || 'image' + }); + this.hide(); + }; + + _proto._resetInputs = function _resetInputs() { + dom["a" /* default */].findAll(this.el, 'input').forEach(function (input) { + input.value = ''; + }); + } + /** + * Remove popup + * @override + */ + ; + + _proto.remove = function remove() { + this.tab.remove(); + + _LayerPopup.prototype.remove.call(this); + }; + + return PopupAddImage; +}(layerpopup); + +/* harmony default export */ var popupAddImage = (popupAddImage_PopupAddImage); +// CONCATENATED MODULE: ./src/js/ui/popupTableUtils.js +function popupTableUtils_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements PopupTableUtils + * @author NHN FE Development Lab + */ + + + + + + +var REMOVE_ROW_MENU_CLASS_NAME = 'te-table-remove-row'; +var DISABLED_MENU_CLASS_NAME = 'te-context-menu-disabled'; +/** + * PopupTableUtils + * It implements table utils popup + * @param {LayerPopupOption} options - layer popup options + */ + +var popupTableUtils_PopupTableUtils = /*#__PURE__*/function (_LayerPopup) { + popupTableUtils_inheritsLoose(PopupTableUtils, _LayerPopup); + + function PopupTableUtils(options) { + var POPUP_CONTENT = "\n \n \n \n \n
    \n \n \n \n
    \n \n "; + options = extend_default()({ + header: false, + className: 'te-popup-table-utils', + content: POPUP_CONTENT + }, options); + return _LayerPopup.call(this, options) || this; + } + /** + * init instance. + * store properties & prepare before initialize DOM + * @param {LayerPopupOption} options - layer popup options + * @private + * @override + */ + + + var _proto = PopupTableUtils.prototype; + + _proto._initInstance = function _initInstance(options) { + _LayerPopup.prototype._initInstance.call(this, options); + + this.eventManager = options.eventManager; + } + /** + * bind DOM events + * @private + * @override + */ + ; + + _proto._initDOMEvent = function _initDOMEvent() { + var _this = this; + + _LayerPopup.prototype._initDOMEvent.call(this); + + this.on('click .te-table-add-row', function () { + return _this.eventManager.emit('command', 'AddRow'); + }); + this.on('click .te-table-add-col', function () { + return _this.eventManager.emit('command', 'AddCol'); + }); + this.on('click .te-table-col-align-left', function () { + return _this.eventManager.emit('command', 'AlignCol', 'left'); + }); + this.on('click .te-table-col-align-center', function () { + return _this.eventManager.emit('command', 'AlignCol', 'center'); + }); + this.on('click .te-table-col-align-right', function () { + return _this.eventManager.emit('command', 'AlignCol', 'right'); + }); + this.on('click .te-table-remove-col', function () { + return _this.eventManager.emit('command', 'RemoveCol'); + }); + this.on('click .te-table-remove', function () { + return _this.eventManager.emit('command', 'RemoveTable'); + }); + + this._bindClickEventOnRemoveRowMenu(); + } + /** + * bind editor events + * @private + * @override + */ + ; + + _proto._initEditorEvent = function _initEditorEvent() { + var _this2 = this; + + _LayerPopup.prototype._initEditorEvent.call(this); + + this.eventManager.listen('focus', function () { + return _this2.hide(); + }); + this.eventManager.listen('mousedown', function () { + return _this2.hide(); + }); + this.eventManager.listen('closeAllPopup', function () { + return _this2.hide(); + }); + this.eventManager.listen('openPopupTableUtils', function (ev) { + var _this2$el$parentNode$ = _this2.el.parentNode.getBoundingClientRect(), + left = _this2$el$parentNode$.left, + top = _this2$el$parentNode$.top; + + _this2._disableRemoveRowMenu(ev.target); + + css_default()(_this2.el, { + position: 'absolute', + top: ev.clientY - top + 5 + "px", + // beside mouse pointer + left: ev.clientX - left + 10 + "px" + }); + + _this2.eventManager.emit('closeAllPopup'); + + _this2.show(); + }); + }; + + _proto._bindClickEventOnRemoveRowMenu = function _bindClickEventOnRemoveRowMenu() { + var _this3 = this; + + this.on("click ." + REMOVE_ROW_MENU_CLASS_NAME, function (ev) { + var target = ev.target; + + if (hasClass_default()(target, DISABLED_MENU_CLASS_NAME)) { + ev.preventDefault(); + } else { + _this3.eventManager.emit('command', 'RemoveRow'); + } + }); + }; + + _proto._disableRemoveRowMenu = function _disableRemoveRowMenu(target) { + var menu = this.el.querySelector("." + REMOVE_ROW_MENU_CLASS_NAME); + dom["a" /* default */].toggleClass(menu, DISABLED_MENU_CLASS_NAME, target.nodeName === 'TH'); + }; + + return PopupTableUtils; +}(layerpopup); + +/* harmony default export */ var popupTableUtils = (popupTableUtils_PopupTableUtils); +// CONCATENATED MODULE: ./src/js/ui/popupAddTable.js +function popupAddTable_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements PopupAddTable + * @author NHN FE Development Lab + */ + + + + +var CLASS_TABLE_SELECTION = 'te-table-selection'; +var CLASS_TABLE_HEADER = 'te-table-header'; +var CLASS_TABLE_BODY = 'te-table-body'; +var CLASS_SELECTION_AREA = 'te-selection-area'; +var CLASS_DESCRIPTION = 'te-description'; +var popupAddTable_POPUP_CONTENT = "\n
    \n
    \n
    \n
    \n
    \n

    \n"; +var CELL_WIDTH = 25; +var CELL_HEIGHT = 17; +var MIN_ROW_INDEX = 7; +var MAX_ROW_INDEX = 14; +var MIN_COL_INDEX = 5; +var MAX_COL_INDEX = 9; +var MIN_ROW_SELECTION_INDEX = 1; +var MIN_COL_SELECTION_INDEX = 1; +var HEADER_ROW_COUNT = 1; +var LAST_BORDER = 1; +/** + * Class PopupAddTable + * It implements Popup to add a table + * @param {LayerPopupOption} options - layer popup option + * @ignore + */ + +var popupAddTable_PopupAddTable = /*#__PURE__*/function (_LayerPopup) { + popupAddTable_inheritsLoose(PopupAddTable, _LayerPopup); + + function PopupAddTable(options) { + options = extend_default()({ + header: false, + className: 'te-popup-add-table', + content: popupAddTable_POPUP_CONTENT + }, options); + return _LayerPopup.call(this, options) || this; + } + /** + * init instance. + * store properties & prepare before initialize DOM + * @param {LayerPopupOption} options - layer popup options + * @private + * @override + */ + + + var _proto = PopupAddTable.prototype; + + _proto._initInstance = function _initInstance(options) { + _LayerPopup.prototype._initInstance.call(this, options); + + this._selectedBound = {}; + this._tableBound = {}; + this._eventManager = options.eventManager; + this._button = options.button; + this._eventHandlers = { + onMousedown: this._selectTableRange.bind(this), + onClick: this._fireCommandEvent.bind(this) + }; + } + /** + * initialize DOM, render popup + * @private + * @override + */ + ; + + _proto._initDOM = function _initDOM() { + _LayerPopup.prototype._initDOM.call(this); + + this._cacheElements(); + + this._setTableSizeByBound(MIN_COL_INDEX, MIN_ROW_INDEX); + } + /** + * bind DOM events + * @private + * @override + */ + ; + + _proto._initDOMEvent = function _initDOMEvent(options) { + _LayerPopup.prototype._initDOMEvent.call(this, options); + + this.on("mousemove ." + CLASS_TABLE_SELECTION, this._eventHandlers.onMousedown); + this.on("click ." + CLASS_TABLE_SELECTION, this._eventHandlers.onClick); + }; + + _proto._selectTableRange = function _selectTableRange(ev) { + var x = ev.pageX - this._selectionOffset.left; + var y = ev.pageY - this._selectionOffset.top; + + var bound = this._getSelectionBoundByOffset(x, y); + + this._resizeTableBySelectionIfNeed(bound.col, bound.row); + + this._setSelectionAreaByBound(bound.col, bound.row); + + this._setDisplayText(bound.col, bound.row); + + this._setSelectedBound(bound.col, bound.row); + }; + + _proto._fireCommandEvent = function _fireCommandEvent() { + var tableSize = this._getSelectedTableSize(); + + this._eventManager.emit('command', 'Table', tableSize.col, tableSize.row); + } + /** + * bind editor events + * @private + * @override + */ + ; + + _proto._initEditorEvent = function _initEditorEvent() { + var _this = this; + + _LayerPopup.prototype._initEditorEvent.call(this); + + this._eventManager.listen('focus', function () { + return _this.hide(); + }); + + this._eventManager.listen('closeAllPopup', function () { + return _this.hide(); + }); + + this._eventManager.listen('openPopupAddTable', function () { + var button = _this._button; + var offsetTop = button.offsetTop, + offsetLeft = button.offsetLeft; + css_default()(_this.el, { + top: offsetTop + dom["a" /* default */].getOuterHeight(button) + "px", + left: offsetLeft + "px" + }); + + _this._eventManager.emit('closeAllPopup'); + + _this.show(); + + var _this$el$querySelecto = _this.el.querySelector("." + CLASS_TABLE_SELECTION).getBoundingClientRect(), + left = _this$el$querySelecto.left, + top = _this$el$querySelecto.top; + + _this._selectionOffset = { + left: left + window.pageXOffset, + top: top + window.pageYOffset + }; + }); + } + /** + * Cache elements for use + * @private + */ + ; + + _proto._cacheElements = function _cacheElements() { + this.header = this.el.querySelector("." + CLASS_TABLE_HEADER); + this.body = this.el.querySelector("." + CLASS_TABLE_BODY); + this.selection = this.el.querySelector("." + CLASS_SELECTION_AREA); + this.desc = this.el.querySelector("." + CLASS_DESCRIPTION); + } + /** + * Resize table if need + * @param {number} col column index + * @param {number} row row index + * @private + */ + ; + + _proto._resizeTableBySelectionIfNeed = function _resizeTableBySelectionIfNeed(col, row) { + var resizedBound = this._getResizedTableBound(col, row); + + if (resizedBound) { + this._setTableSizeByBound(resizedBound.col, resizedBound.row); + } + } + /** + * Get resized table bound if Need + * @param {number} col column index + * @param {number} row row index + * @returns {object} bound + * @private + */ + ; + + _proto._getResizedTableBound = function _getResizedTableBound(col, row) { + var resizedCol, resizedRow, resizedBound; + + if (col >= MIN_COL_INDEX && col < MAX_COL_INDEX) { + resizedCol = col + 1; + } else if (col < MIN_COL_INDEX) { + resizedCol = MIN_COL_INDEX; + } + + if (row >= MIN_ROW_INDEX && row < MAX_ROW_INDEX) { + resizedRow = row + 1; + } else if (row < MIN_ROW_INDEX) { + resizedRow = MIN_ROW_INDEX; + } + + if (this._isNeedResizeTable(resizedCol, resizedRow)) { + resizedBound = { + row: resizedRow || this._tableBound.row, + col: resizedCol || this._tableBound.col + }; + } + + return resizedBound; + } + /** + * check if need resize table + * @param {number} col column index + * @param {number} row row index + * @returns {boolean} result + * @private + */ + ; + + _proto._isNeedResizeTable = function _isNeedResizeTable(col, row) { + return col && col !== this._tableBound.col || row && row !== this._tableBound.row; + } + /** + * Get bound by offset + * @param {number} x offset + * @param {number} y offset + * @returns {object} bound + * @private + */ + ; + + _proto._getBoundByOffset = function _getBoundByOffset(x, y) { + var row = parseInt(y / CELL_HEIGHT, 10); + var col = parseInt(x / CELL_WIDTH, 10); + return { + row: row, + col: col + }; + } + /** + * Get offset by bound + * @param {number} col column index + * @param {number} row row index + * @returns {object} offset + * @private + */ + ; + + _proto._getOffsetByBound = function _getOffsetByBound(col, row) { + var x = col * CELL_WIDTH + CELL_WIDTH, + y = row * CELL_HEIGHT + CELL_HEIGHT; + return { + x: x, + y: y + }; + } + /** + * Set table size with bound + * @param {number} col column index + * @param {number} row row index + * @private + */ + ; + + _proto._setTableSizeByBound = function _setTableSizeByBound(col, row) { + var boundOffset = this._getOffsetByBound(col, row - HEADER_ROW_COUNT); + + this._setTableSize(boundOffset.x, boundOffset.y); + + this._tableBound.row = row; + this._tableBound.col = col; + } + /** + * Get selection bound that process with range by offset + * @param {number} x offset + * @param {number} y offset + * @returns {object} bound + * @private + */ + ; + + _proto._getSelectionBoundByOffset = function _getSelectionBoundByOffset(x, y) { + var bound = this._getBoundByOffset(x, y); + + if (bound.row < MIN_ROW_SELECTION_INDEX) { + bound.row = MIN_ROW_SELECTION_INDEX; + } else if (bound.row > this._tableBound.row) { + bound.row = this._tableBound.row; + } + + if (bound.col < MIN_COL_SELECTION_INDEX) { + bound.col = MIN_COL_SELECTION_INDEX; + } else if (bound.col > this._tableBound.col) { + bound.col = this._tableBound.col; + } + + return bound; + } + /** + * Set selection area with bound + * @param {number} col column index + * @param {number} row row index + * @private + */ + ; + + _proto._setSelectionAreaByBound = function _setSelectionAreaByBound(col, row) { + var boundOffset = this._getOffsetByBound(col, row); + + this._setSelectionArea(boundOffset.x, boundOffset.y); + } + /** + * Set selected bound + * @param {number} col column index + * @param {number} row row index + * @private + */ + ; + + _proto._setSelectedBound = function _setSelectedBound(col, row) { + this._selectedBound.col = col; + this._selectedBound.row = row; + } + /** + * Get selected table size + * @returns {object} bound + * @private + */ + ; + + _proto._getSelectedTableSize = function _getSelectedTableSize() { + return { + row: this._selectedBound.row + 1, + col: this._selectedBound.col + 1 + }; + } + /** + * Set selected table size text for display + * @param {number} col column index + * @param {number} row row index + * @private + */ + ; + + _proto._setDisplayText = function _setDisplayText(col, row) { + this.desc.innerHTML = col + 1 + " x " + (row + 1); + } + /** + * Set table element size + * @param {number} x offset + * @param {number} y offset + * @private + */ + ; + + _proto._setTableSize = function _setTableSize(x, y) { + x += LAST_BORDER; + y += LAST_BORDER; + css_default()(this.header, { + height: CELL_HEIGHT + "px", + width: x + "px" + }); + css_default()(this.body, { + height: y + "px", + width: x + "px" + }); + css_default()(this.el, { + width: x + 30 + "px" + }); + } + /** + * Set selection element size + * @param {number} x offset + * @param {number} y offset + * @private + */ + ; + + _proto._setSelectionArea = function _setSelectionArea(x, y) { + x += LAST_BORDER; + y += LAST_BORDER; + css_default()(this.selection, { + height: y + "px", + width: x + "px" + }); + }; + + _proto.remove = function remove() { + this.off("mousemove ." + CLASS_TABLE_SELECTION, this._eventHandlers.onMousedown); + this.off("click ." + CLASS_TABLE_SELECTION, this._eventHandlers.onClick); + + _LayerPopup.prototype.remove.call(this); + }; + + return PopupAddTable; +}(layerpopup); + +popupAddTable_PopupAddTable.CELL_WIDTH = CELL_WIDTH; +popupAddTable_PopupAddTable.CELL_HEIGHT = CELL_HEIGHT; +popupAddTable_PopupAddTable.MIN_ROW_SELECTION_INDEX = MIN_ROW_SELECTION_INDEX; +popupAddTable_PopupAddTable.MIN_COL_SELECTION_INDEX = MIN_COL_SELECTION_INDEX; +/* harmony default export */ var popupAddTable = (popupAddTable_PopupAddTable); +// CONCATENATED MODULE: ./src/js/ui/popupAddHeading.js +function popupAddHeading_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements PopupAddHeading + * @author NHN FE Development Lab + */ + + + + + +/** + * Class PopupAddHeading + * It implements Popup to add headings + * @param {LayerPopupOption} options - layer popup option + * @ignore + */ + +var popupAddHeading_PopupAddHeading = /*#__PURE__*/function (_LayerPopup) { + popupAddHeading_inheritsLoose(PopupAddHeading, _LayerPopup); + + function PopupAddHeading(options) { + var POPUP_CONTENT = "\n
      \n
    • " + i18n.get('Heading') + " 1

    • \n
    • " + i18n.get('Heading') + " 2

    • \n
    • " + i18n.get('Heading') + " 3

    • \n
    • " + i18n.get('Heading') + " 4

    • \n
    • " + i18n.get('Heading') + " 5
    • \n
    • " + i18n.get('Heading') + " 6
    • \n
    • " + i18n.get('Paragraph') + "
    • \n
    \n "; + options = extend_default()({ + header: false, + className: 'te-heading-add', + content: POPUP_CONTENT + }, options); + return _LayerPopup.call(this, options) || this; + } + /** + * init instance. + * store properties & prepare before initialize DOM + * @param {LayerPopupOption} options - layer popup options + * @private + * @override + */ + + + var _proto = PopupAddHeading.prototype; + + _proto._initInstance = function _initInstance(options) { + _LayerPopup.prototype._initInstance.call(this, options); + + this._eventManager = options.eventManager; + this._button = options.button; + } + /** + * bind DOM events + * @private + * @override + */ + ; + + _proto._initDOMEvent = function _initDOMEvent() { + var _this = this; + + _LayerPopup.prototype._initDOMEvent.call(this); + + this.on('click li', function (ev) { + var li = dom["a" /* default */].closest(ev.target, 'li'); + + _this._eventManager.emit('command', li.getAttribute('data-type'), li.getAttribute('data-value')); + }); + } + /** + * bind editor events + * @private + * @override + */ + ; + + _proto._initEditorEvent = function _initEditorEvent() { + var _this2 = this; + + _LayerPopup.prototype._initEditorEvent.call(this); + + this._eventManager.listen('focus', this.hide.bind(this)); + + this._eventManager.listen('closeAllPopup', this.hide.bind(this)); + + this._eventManager.listen('openHeadingSelect', function () { + var button = _this2._button; + var offsetTop = button.offsetTop, + offsetLeft = button.offsetLeft; + css_default()(_this2.el, { + top: offsetTop + dom["a" /* default */].getOuterHeight(button) + "px", + left: offsetLeft + "px" + }); + + _this2._eventManager.emit('closeAllPopup'); + + _this2.show(); + }); + }; + + return PopupAddHeading; +}(layerpopup); + +/* harmony default export */ var popupAddHeading = (popupAddHeading_PopupAddHeading); +// CONCATENATED MODULE: ./src/js/ui/popupCodeBlockLanguages.js +function popupCodeBlockLanguages_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements popup code block languages + * @author NHN FE Development Lab + */ + + + + + + + + +var BUTTON_CLASS_PREFIX = 'te-popup-code-block-lang-'; + +function getButtonsHTML(languages) { + return languages.map(function (lang) { + return ""; + }).join(''); +} +/** + * Class Popup code block languages select list + * @param {LayerPopupOption} options - layer popup option + * @ignore + */ + + +var popupCodeBlockLanguages_PopupCodeBlockLanguages = /*#__PURE__*/function (_LayerPopup) { + popupCodeBlockLanguages_inheritsLoose(PopupCodeBlockLanguages, _LayerPopup); + + function PopupCodeBlockLanguages(options) { + var _options = options, + languages = _options.languages; + options = extend_default()({ + header: false, + className: 'te-popup-code-block-languages', + content: getButtonsHTML(languages) + }, options); + return _LayerPopup.call(this, options) || this; + } + /** + * init instance. + * store properties & prepare before initialize DOM + * @param {LayerPopupOption} options - layer popup options + * @private + * @override + */ + + + var _proto = PopupCodeBlockLanguages.prototype; + + _proto._initInstance = function _initInstance(options) { + var _this = this; + + _LayerPopup.prototype._initInstance.call(this, options); + + this.eventManager = options.eventManager; + this._onSelectedLanguage = null; + this._onDismissed = null; + this._currentButton = null; + this._buttons = null; + this._languages = options.languages; + + this._btnMousedownHandler = function (event) { + var language = event.target.getAttribute('data-lang'); + + if (_this._onSelectedLanguage) { + _this._onSelectedLanguage(language); + } + + _this.hide(); + }; + } + /** + * initialize DOM, render popup + * @private + * @override + */ + ; + + _proto._initDOM = function _initDOM(options) { + _LayerPopup.prototype._initDOM.call(this, options); + + css_default()(this.el, 'zIndex', 10000); + this._buttons = dom["a" /* default */].findAll(this.el, 'button'); + + this._activateButtonByIndex(0); + } + /** + * bind DOM events + * @private + * @override + */ + ; + + _proto._initDOMEvent = function _initDOMEvent() { + _LayerPopup.prototype._initDOMEvent.call(this); + + this._addBtnMouseDownHandler(); + } + /** + * bind editor events + * @private + * @override + */ + ; + + _proto._initEditorEvent = function _initEditorEvent() { + var _this2 = this; + + _LayerPopup.prototype._initEditorEvent.call(this); + + this.eventManager.listen('openPopupCodeBlockLanguages', function (data) { + _this2.show(data.callback); + + css_default()(_this2.el, { + top: data.offset.top + "px" + }); + css_default()(_this2.el, { + left: data.offset.left + "px" + }); + + _this2.setCurrentLanguage(data.language); + + return _this2; + }); + this.eventManager.listen('focus', function () { + return _this2.hide(); + }); + this.eventManager.listen('mousedown', function () { + return _this2.hide(); + }); + this.eventManager.listen('closeAllPopup', function () { + return _this2.hide(); + }); + this.eventManager.listen('closePopupCodeBlockLanguages', function () { + return _this2.hide(); + }); + this.eventManager.listen('scroll', function () { + return _this2.hide(); + }); + this.eventManager.listen('setCodeBlockLanguages', function (languages) { + return _this2._changeLanguageButtons(languages); + }); + } + /** + * activate an item by index + * @param {number} index - item index + * @private + */ + ; + + _proto._activateButtonByIndex = function _activateButtonByIndex(index) { + if (this._currentButton) { + removeClass_default()(this._currentButton, 'active'); + } + + if (this._buttons.length) { + this._currentButton = this._buttons[index]; + addClass_default()(this._currentButton, 'active'); + + this._currentButton.scrollIntoView(); + } + } + /** + * move to prev language + */ + ; + + _proto.prev = function prev() { + var index = inArray_default()(this._currentButton, this._buttons) - 1; + + if (index < 0) { + index = this._buttons.length - 1; + } + + this._activateButtonByIndex(index); + } + /** + * move to next language + */ + ; + + _proto.next = function next() { + var index = inArray_default()(this._currentButton, this._buttons) + 1; + + if (index >= this._buttons.length) { + index = 0; + } + + this._activateButtonByIndex(index); + } + /** + * current language + * @returns {string} language + */ + ; + + _proto.getCurrentLanguage = function getCurrentLanguage() { + var language = this._currentButton.getAttribute('data-lang'); + + return language; + } + /** + * set current language + * @param {string} language - current language + */ + ; + + _proto.setCurrentLanguage = function setCurrentLanguage(language) { + var item = this._buttons.filter(function (button) { + return matches_default()(button, "." + BUTTON_CLASS_PREFIX + language); + }); + + if (item.length > 0) { + var index = inArray_default()(item[0], this._buttons); + + this._activateButtonByIndex(index); + } + } + /** + * show popup + * @param {object} callback - to be called on language selected & dismissed + * @override + */ + ; + + _proto.show = function show(callback) { + this._onSelectedLanguage = callback.selected; + this._onDismissed = callback.dismissed; + + _LayerPopup.prototype.show.call(this); + } + /** + * hide popup + * @override + */ + ; + + _proto.hide = function hide() { + if (this._onDismissed) { + this._onDismissed(); + } + + this._onSelectedLanguage = null; + this._onDismissed = null; + + _LayerPopup.prototype.hide.call(this); + }; + + _proto._addBtnMouseDownHandler = function _addBtnMouseDownHandler() { + var _this3 = this; + + this._languages.forEach(function (lang) { + _this3.off("mousedown ." + BUTTON_CLASS_PREFIX + lang, _this3._btnMousedownHandler); + + _this3.on("mousedown ." + BUTTON_CLASS_PREFIX + lang, _this3._btnMousedownHandler); + }); + }; + + _proto._changeLanguageButtons = function _changeLanguageButtons(languages) { + this._languages = languages; + + if (languages && languages.length) { + this.content = getButtonsHTML(languages); + this.setContent(this.content); + + this._addBtnMouseDownHandler(); + + this._buttons = dom["a" /* default */].findAll(this.el, 'button'); + + this._activateButtonByIndex(0); + } + }; + + return PopupCodeBlockLanguages; +}(layerpopup); + +/* harmony default export */ var popupCodeBlockLanguages = (popupCodeBlockLanguages_PopupCodeBlockLanguages); +// CONCATENATED MODULE: ./src/js/ui/scrollSyncSplit.js +/** + * @fileoverview Implements scroll sync split + * @author NHN FE Development Lab + */ + + + + + + +var CLASS_SPLIT_SCROLL = 'tui-split-scroll'; +var CLASS_SINGLE_CONTENT = 'single-content'; +var CLASS_SCROLL_SYNC = 'scroll-sync'; +var CLASS_SCROLL_WRAPPER = 'tui-split-scroll-wrapper'; +var CLASS_SCROLL_CONTENT = 'tui-split-scroll-content'; +var CLASS_SPLITTER = 'tui-splitter'; +var EVENT_REQUIRE_SCROLL_INTO_VIEW = 'requireScrollIntoView'; +var CLASS_CONTENT_LEFT = 'tui-split-content-left'; +var CLASS_CONTENT_RIGHT = 'tui-split-content-right'; +var CLASS_CONTENT = { + left: CLASS_CONTENT_LEFT, + right: CLASS_CONTENT_RIGHT +}; +/** + * Class ScrollSyncSplit + * @param {Element} baseElement - an element which attach a splitSyncSplit + * @param {Element} leftElement - an element to be on left side split view + * @param {Element} rightElement - an element to be on right side split view + * @param {object} options - options + * @param {boolean} [options.showScrollSyncButton=false] - show scroll sync button on top right corner + * @param {boolean} [options.scrollSync=true] - true for enable scroll sync + * @param {boolean} [options.splitView=true] - true for split, false for single view + * @ignore + */ + +var scrollSyncSplit_ScrollSyncSplit = /*#__PURE__*/function () { + function ScrollSyncSplit(baseElement, leftElement, rightElement, options) { + if (options === void 0) { + options = {}; + } + + options = extend_default()({ + showScrollSyncButton: false, + scrollSync: true, + splitView: true + }, options); + this._baseElement = baseElement; + this._eventManager = options.eventManager; + /** + * left, right side content elements + * @type {HTMLElement[]} + * @private + */ + + this._contentElements = []; + + this._initDom(leftElement, rightElement, options); + + this._initDomEvent(); + } + + var _proto = ScrollSyncSplit.prototype; + + _proto._initDom = function _initDom(leftElement, rightElement, options) { + var el = document.createElement('div'); + el.className = CLASS_SPLIT_SCROLL; + this._el = el; + var scrollWrapper = document.createElement('div'); + scrollWrapper.className = CLASS_SCROLL_WRAPPER; + this._scrollWrapper = scrollWrapper; + + this._setScrollSync(options.scrollSync); + + this.setSplitView(options.splitView); + var contentWrapper = document.createElement('div'); + contentWrapper.className = CLASS_SCROLL_CONTENT; + this._contentWrapper = contentWrapper; + var splitter = document.createElement('div'); + splitter.className = CLASS_SPLITTER; + + this._baseElement.appendChild(el); + + el.appendChild(scrollWrapper); + scrollWrapper.appendChild(contentWrapper); + scrollWrapper.appendChild(splitter); + + this._setLeft(leftElement); + + this._setRight(rightElement); + }; + + _proto._initDomEvent = function _initDomEvent() { + this._contentWrapper.addEventListener('scroll', this.sync.bind(this)); + }; + + _proto._requireScrollIntoView = function _requireScrollIntoView(element) { + var _element$getBoundingC = element.getBoundingClientRect(), + targetTop = _element$getBoundingC.top, + targetBottom = _element$getBoundingC.bottom; + + var wrapperElement; + + if (this.isScrollSynced()) { + wrapperElement = this._contentWrapper; + } else if (dom["a" /* default */].parents(element, this._contentElements.left).length) { + wrapperElement = this._contentElements.left; + } else if (dom["a" /* default */].parents(element, this._contentElements.right).length) { + wrapperElement = this._contentElements.right; + } else { + return; + } + + var _wrapperElement$getBo = wrapperElement.getBoundingClientRect(), + wrapperTop = _wrapperElement$getBo.top, + wrapperBottom = _wrapperElement$getBo.bottom; + + if (targetTop < wrapperTop) { + wrapperElement.scrollTop = wrapperElement.scrollTop + targetTop - wrapperTop; + } else if (targetBottom > wrapperBottom) { + wrapperElement.scrollTop = wrapperElement.scrollTop + targetBottom - wrapperBottom; + } + + this.sync(); + } + /** + * set content element for given side + * @param {Element} element - content element + * @param {string} side - 'left' | 'right' + * @private + */ + ; + + _proto._setContentElement = function _setContentElement(element, side) { + var _this = this; + + var contentElement = this._contentElements[side]; + + if (contentElement) { + this._eventManager.removeEventHandler(EVENT_REQUIRE_SCROLL_INTO_VIEW); + + this._contentWrapper.removeChild(contentElement); + } + + addClass_default()(element, CLASS_CONTENT[side]); + + this._contentWrapper.appendChild(element); + + this._eventManager.listen(EVENT_REQUIRE_SCROLL_INTO_VIEW, function (ev) { + return _this._requireScrollIntoView(ev); + }); + + this._eventManager.listen('requireScrollSync', function () { + return _this.sync(); + }); + + this._contentElements[side] = element; + this.sync(); + } + /** + * set left side element + * @param {Element} element - an element to be on left side split view + * @private + */ + ; + + _proto._setLeft = function _setLeft(element) { + this._setContentElement(element, 'left'); + } + /** + * set right side element + * @param {Element} element - an element to be on right side split view + * @private + */ + ; + + _proto._setRight = function _setRight(element) { + this._setContentElement(element, 'right'); + }; + + _proto._setScrollSync = function _setScrollSync(activate) { + dom["a" /* default */].toggleClass(this._el, CLASS_SCROLL_SYNC, activate); + } + /** + * toggle multi scroll + */ + ; + + _proto.toggleScrollSync = function toggleScrollSync() { + dom["a" /* default */].toggleClass(this._el, CLASS_SCROLL_SYNC); + }; + + _proto.setSplitView = function setSplitView(activate) { + if (!activate) { + addClass_default()(this._el, CLASS_SINGLE_CONTENT); + } else { + removeClass_default()(this._el, CLASS_SINGLE_CONTENT); + } + } + /** + * toggle split + */ + ; + + _proto.toggleSplitView = function toggleSplitView() { + dom["a" /* default */].toggleClass(this._el, CLASS_SINGLE_CONTENT); + } + /** + * is scroll synced + * @returns {boolean} - true for synced, false for each scroll + */ + ; + + _proto.isScrollSynced = function isScrollSynced() { + return hasClass_default()(this._el, CLASS_SCROLL_SYNC); + } + /** + * is split view + * @returns {boolean} - true for split view, false for single view + */ + ; + + _proto.isSplitView = function isSplitView() { + return !hasClass_default()(this._el, CLASS_SINGLE_CONTENT); + } + /** + * sync scroll + */ + ; + + _proto.sync = function sync() { + if (!this._contentElements.left || !this._contentElements.right) { + return; + } + + var wrapperHeight = this._contentWrapper.clientHeight; + var scrollTop = this._contentWrapper.scrollTop; + var leftElement = this._contentElements.left; + var rightElement = this._contentElements.right; + var scrollingElement = leftElement.offsetHeight - wrapperHeight > 0 ? leftElement : rightElement; + var followingElement = scrollingElement === leftElement ? rightElement : leftElement; + var scrollingElementHeight = scrollingElement.offsetHeight; + var scrollingElementScrollMax = Math.max(scrollingElementHeight - wrapperHeight, 0); + var followingElementHeight = Math.max(followingElement.offsetHeight, wrapperHeight); + var followingElementTopMax = scrollingElementHeight - followingElementHeight; + css_default()(scrollingElement, { + top: 0 + }); + css_default()(followingElement, { + top: scrollTop / scrollingElementScrollMax * followingElementTopMax + "px" + }); + } + /** + * scroll top + * @param {number} top - scroll top in pixel + */ + ; + + _proto.scrollTop = function scrollTop(top) { + this._contentWrapper.scrollTop = top; + }; + + return ScrollSyncSplit; +}(); + +/* harmony default export */ var scrollSyncSplit = (scrollSyncSplit_ScrollSyncSplit); +// CONCATENATED MODULE: ./src/js/codeBlockEditor.js +function codeBlockEditor_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements code block editor + * @author NHN FE Development Lab + */ + +/** + * Class Code Block Editor + * @param {HTMLElement} el - code block editor container element + * @param {EventManager} eventManager - event manager + * @ignore + */ + +var CodeBlockEditor = /*#__PURE__*/function (_CodeMirrorExt) { + codeBlockEditor_inheritsLoose(CodeBlockEditor, _CodeMirrorExt); + + function CodeBlockEditor(el, eventManager) { + var _this; + + _this = _CodeMirrorExt.call(this, el, { + singleCursorHeightPerLine: false, + theme: 'none' + }) || this; + _this._language = ''; + _this._eventManager = eventManager; + + _this._initEvent(); + + return _this; + } + + var _proto = CodeBlockEditor.prototype; + + _proto._initEvent = function _initEvent() { + var _this2 = this; + + this.on('cursorActivity', this._onRequireScrollIntoView.bind(this)); + this.on('beforeChange', function (cm, ev) { + if (ev.origin === 'paste') { + _this2._eventManager.emit('pasteBefore', { + source: 'codeblock', + data: ev + }); + } + }); + }; + + _proto._onRequireScrollIntoView = function _onRequireScrollIntoView() { + var _this3 = this; + + var cursor = this.getCursor(); + var wrapper = this.getWrapperElement(); // CodeMirror cursorActivity event fires before actually attach a new line element to DOM + // we should proceed at next tick + + setTimeout(function () { + var lineElement = wrapper.querySelector("pre:nth-child(" + (cursor.line + 1) + ")"); + + if (lineElement) { + _this3._eventManager.emit('requireScrollIntoView', lineElement); + } + }, 0); + } + /** + * load code from code block element + * @param {HTMLElement} codeBlockElement - code block element + */ + ; + + _proto.load = function load(codeBlockElement) { + var el = codeBlockElement.cloneNode(true); + this.setLanguage(el.getAttribute('data-language') || ''); + this.setEditorCodeText(el.textContent); + } + /** + * save code to code block element + * @param {HTMLElement} codeBlockElement - code block element + */ + ; + + _proto.save = function save(codeBlockElement) { + codeBlockElement.innerHTML = ''; + codeBlockElement.textContent = this.getEditorCodeText(); + codeBlockElement.setAttribute('data-language', this._language); + + this._eventManager.emit('changeLanguage'); + } + /** + * clear code and language + */ + ; + + _proto.clear = function clear() { + this.setLanguage(''); + this.setEditorCodeText(''); + } + /** + * get code language + * @returns {string} - code language + */ + ; + + _proto.getLanguage = function getLanguage() { + return this._language; + } + /** + * set code language + * @param {string} [language=''] - code language + */ + ; + + _proto.setLanguage = function setLanguage(language) { + if (language === void 0) { + language = ''; + } + + this._language = language; + } + /** + * get code text + * @returns {string} - code text + */ + ; + + _proto.getEditorCodeText = function getEditorCodeText() { + return this.getValue(); + } + /** + * set code text + * @param {string} [code=''] - code text + */ + ; + + _proto.setEditorCodeText = function setEditorCodeText(code) { + if (code === void 0) { + code = ''; + } + + this.setValue(code); + } + /** + * refresh. call if codemirror resized + */ + ; + + _proto.refresh = function refresh() { + this.cm.refresh(); + }; + + return CodeBlockEditor; +}(codeMirrorExt); + +/* harmony default export */ var codeBlockEditor = (CodeBlockEditor); +// EXTERNAL MODULE: ./src/js/preview.js + 1 modules +var js_preview = __webpack_require__(38); + +// CONCATENATED MODULE: ./src/js/codeBlockPreview.js +function codeBlockPreview_assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function codeBlockPreview_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements CodeBlockPreview + * @author NHN FE Development Lab + */ + +/** + * Class Code block preview + * @param {HTMLElement} el - base element + * @param {EventManager} eventManager - event manager + * @param {Convertor} convertor - convertor + * @param {CodeBlockEditor} codeBlockEditor - code block editor + * @ignore + */ + +var CodeBlockPreview = /*#__PURE__*/function (_Preview) { + codeBlockPreview_inheritsLoose(CodeBlockPreview, _Preview); + + function CodeBlockPreview(el, eventManager, convertor, codeBlockEditor) { + var _this; + + _this = _Preview.call(this, el, eventManager, convertor, true) || this; + _this._codeBlockEditor = codeBlockEditor; + + _this._initEvent(); + + _this.lazyRunner.registerLazyRunFunction('refresh', _this.refresh, _this.delayCodeBlockTime, codeBlockPreview_assertThisInitialized(_this)); + + return _this; + } + + var _proto = CodeBlockPreview.prototype; + + _proto._initEvent = function _initEvent() { + var _this2 = this; + + this._codeBlockEditor.on('update', function () { + return _this2.lazyRunner.run('refresh'); + }); + } + /** + * refresh preview + * @override + */ + ; + + _proto.refresh = function refresh() { + var language = this._codeBlockEditor.getLanguage(); + + var codeText = this._codeBlockEditor.getEditorCodeText(); + + _Preview.prototype.refresh.call(this, "```" + language + "\n" + codeText + "\n```"); + + this.eventManager.emit('requireScrollSync'); + } + /** + * clear preview + */ + ; + + _proto.clear = function clear() { + _Preview.prototype.render.call(this, ''); + }; + + return CodeBlockPreview; +}(js_preview["a" /* default */]); + +/* harmony default export */ var codeBlockPreview = (CodeBlockPreview); +// CONCATENATED MODULE: ./src/js/ui/codeBlockLanguagesCombo.js +/** + * @fileoverview Implements UI code block languages combo + * @author NHN FE Development Lab + */ + + + + + + + +/** + * Class CodeBlockLanguagesCombo + * @param {EventManager} eventManager - event manager instance + * @ignore + */ + +var codeBlockLanguagesCombo_CodeBlockLanguagesCombo = /*#__PURE__*/function () { + function CodeBlockLanguagesCombo(eventManager, languages) { + this._eventManager = eventManager; + this._languages = languages; + + this._initDOM(); + + this._initDOMEvent(); + + this._initEvent(); + } + + var _proto = CodeBlockLanguagesCombo.prototype; + + _proto._initDOM = function _initDOM() { + this._inputLanguage = dom["a" /* default */].createElementWith(""); + this._wrapper = dom["a" /* default */].createElementWith(""); + + this._wrapper.appendChild(this._inputLanguage); + + this._hide(); + }; + + _proto._initDOMEvent = function _initDOMEvent() { + var _this = this; + + this._inputLanguage.addEventListener('keydown', function (event) { + return _this._onKeyEvent(event); + }); + + this._inputLanguage.addEventListener('focus', function () { + return _this._showPopupCodeBlockLanguages(); + }); + + this._inputLanguage.addEventListener('focusout', function () { + return _this._onFocusOut(); + }); + + this._wrapper.addEventListener('mousedown', function (ev) { + if (ev.target !== _this._wrapper) { + return; + } + + ev.preventDefault(); + + _this._toggleFocus(); + }); + }; + + _proto._initEvent = function _initEvent() { + var _this2 = this; + + this._eventManager.listen('setCodeBlockLanguages', function (languages) { + _this2._languages = languages; + + if (languages && languages.length) { + _this2._show(); + } else { + _this2._hide(); + } + }); + } + /** + * show popup + * @private + */ + ; + + _proto._showPopupCodeBlockLanguages = function _showPopupCodeBlockLanguages() { + var _this3 = this; + + var clientRect = this._inputLanguage.getBoundingClientRect(); + + addClass_default()(this._wrapper, 'active'); + this.active = true; + this._popupCodeBlockLanguages = this._eventManager.emitReduce('openPopupCodeBlockLanguages', { + language: this._prevStoredLanguage, + offset: { + left: clientRect.left, + top: clientRect.bottom + }, + callback: { + selected: function selected(selectedLanguage) { + return _this3._onLanguageSelectedFromList(selectedLanguage); + }, + dismissed: function dismissed() { + _this3._popupCodeBlockLanguages = null; + } + } + }); + }; + + _proto._toggleFocus = function _toggleFocus() { + var inputLanguage = this._inputLanguage; + + if (hasClass_default()(this._wrapper, 'active')) { + inputLanguage.blur(); + } else { + inputLanguage.focus(); + } + }; + + _proto._onFocusOut = function _onFocusOut() { + removeClass_default()(this._wrapper, 'active'); + this._inputLanguage.value = this._prevStoredLanguage; + + this._hidePopupCodeBlockLanguages(); + }; + + _proto._onKeyEvent = function _onKeyEvent(event) { + if (this._popupCodeBlockLanguages) { + switch (event.which) { + case keyMapper.keyCode('UP'): + this._popupCodeBlockLanguages.prev(); + + event.preventDefault(); + break; + + case keyMapper.keyCode('DOWN'): + this._popupCodeBlockLanguages.next(); + + event.preventDefault(); + break; + + case keyMapper.keyCode('ENTER'): + case keyMapper.keyCode('TAB'): + { + var language = this._popupCodeBlockLanguages.getCurrentLanguage(); + + this._inputLanguage.value = language; + + this._storeInputLanguage(); + + event.preventDefault(); + break; + } + + default: + this._popupCodeBlockLanguages.hide(); + + } + } else if (event.which === keyMapper.keyCode('ENTER') || event.which === keyMapper.keyCode('TAB')) { + this._storeInputLanguage(); + + event.preventDefault(); + } + }; + + _proto._onLanguageSelectedFromList = function _onLanguageSelectedFromList(selectedLanguage) { + this._inputLanguage.value = selectedLanguage; + + this._storeInputLanguage(); + } + /** + * set a callback to be called on language selected + * @param {function} callback - callback function + * @protected + */ + ; + + _proto.setOnLanguageSelected = function setOnLanguageSelected(callback) { + this._onLanguageSelected = callback; + } + /** + * hide popup + * @private + */ + ; + + _proto._hidePopupCodeBlockLanguages = function _hidePopupCodeBlockLanguages() { + this._eventManager.emit('closePopupCodeBlockLanguages'); + } + /** + * set language + * @param {string} language - code block language + * @protected + */ + ; + + _proto.setLanguage = function setLanguage(language) { + this._prevStoredLanguage = language; + this._inputLanguage.value = language; + } + /** + * store selection(typed) language & hide popup + * @private + */ + ; + + _proto._storeInputLanguage = function _storeInputLanguage() { + var selectedLanguage = this._inputLanguage.value; + this.setLanguage(selectedLanguage); + + if (this._onLanguageSelected) { + this._onLanguageSelected(selectedLanguage); + } + + this._hidePopupCodeBlockLanguages(); + } + /** + * get element body + * @returns {HTMLElement} - CodeBlockLanguagesCombo body element + * @protected + */ + ; + + _proto.getElement = function getElement() { + return this._wrapper; + }; + + _proto._show = function _show() { + css_default()(this._wrapper, { + display: 'inline-block' + }); + }; + + _proto._hide = function _hide() { + css_default()(this._wrapper, { + display: 'none' + }); + }; + + return CodeBlockLanguagesCombo; +}(); + +/* harmony default export */ var ui_codeBlockLanguagesCombo = (codeBlockLanguagesCombo_CodeBlockLanguagesCombo); +// CONCATENATED MODULE: ./src/js/ui/popupCodeBlockEditor.js +function popupCodeBlockEditor_inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +/** + * @fileoverview Implements popup code block editor + * @author NHN FE Development Lab + */ + + + + + + + + + +var popupCodeBlockEditor_CLASS_PREFIX = 'popup-editor-'; +var popupCodeBlockEditor_CLASS_OK_BUTTON = 'te-ok-button'; +var popupCodeBlockEditor_CLASS_CLOSE_BUTTON = 'te-close-button'; +var CLASS_POPUP_CLOSE_BUTTON = 'tui-popup-close-button'; +var TEMPLATE_HEADER_BUTTONS = "\n \n \n \n \n"; +/** + * Class popup code block editor + * @param {LayerPopupOption} options - layer popup option + * @ignore + */ + +var popupCodeBlockEditor_PopupCodeBlockEditor = /*#__PURE__*/function (_LayerPopup) { + popupCodeBlockEditor_inheritsLoose(PopupCodeBlockEditor, _LayerPopup); + + function PopupCodeBlockEditor(options) { + var TEMPLATE_CONTENT = "\n
    \n
    \n \n \n
    \n "; + options = extend_default()({ + header: true, + title: 'CodeBlock Editor', + content: TEMPLATE_CONTENT, + className: 'tui-popup-code-block-editor', + headerButtons: TEMPLATE_HEADER_BUTTONS, + modal: true + }, options); + return _LayerPopup.call(this, options) || this; + } + /** + * init instance. + * store properties & prepare before initialize DOM + * @param {LayerPopupOption} options - layer popup options + * @private + * @override + */ + + + var _proto = PopupCodeBlockEditor.prototype; + + _proto._initInstance = function _initInstance(options) { + _LayerPopup.prototype._initInstance.call(this, options); + + this.eventManager = options.eventManager; + this.convertor = options.convertor; + this.languages = options.languages; + } + /** + * initialize DOM, render popup + * @private + * @override + */ + ; + + _proto._initDOM = function _initDOM(options) { + _LayerPopup.prototype._initDOM.call(this, options); + + var el = this.el, + eventManager = this.eventManager; + this._body = el.querySelector("." + popupCodeBlockEditor_CLASS_PREFIX + "body"); + this._toggleFitButton = el.querySelector("." + popupCodeBlockEditor_CLASS_PREFIX + "toggle-fit"); + this._togglePreviewButton = el.querySelector("." + popupCodeBlockEditor_CLASS_PREFIX + "toggle-preview"); + this._toggleScrollButton = el.querySelector("." + popupCodeBlockEditor_CLASS_PREFIX + "toggle-scroll"); + this._okButton = el.querySelector("." + popupCodeBlockEditor_CLASS_OK_BUTTON); + this._closeButton = el.querySelector("." + popupCodeBlockEditor_CLASS_CLOSE_BUTTON); + this._codeMirrorWrapper = this._createCodeBlockEditor(); + this._previewWrapper = this._createPreview(); + this._scrollSyncSplit = new scrollSyncSplit(this._body, this._codeMirrorWrapper, this._previewWrapper, { + eventManager: eventManager + }); + + this._updateFitWindowButton(); + + this._updatePreviewButton(); + + this._updateScrollButton(); + + this._codeBlockLanguagesCombo = this._createCodeBlockLanguagesCombo(); + } + /** + * bind DOM events + * @private + * @override + */ + ; + + _proto._initDOMEvent = function _initDOMEvent() { + var _this = this; + + _LayerPopup.prototype._initDOMEvent.call(this); + + this.on('scroll', function (ev) { + return ev.preventDefault(); + }); + this.on("click ." + popupCodeBlockEditor_CLASS_PREFIX + "toggle-fit", function () { + return _this._toggleFitToWindow(); + }); + this.on("click ." + popupCodeBlockEditor_CLASS_PREFIX + "toggle-preview", function () { + return _this._togglePreview(); + }); + this.on("click ." + popupCodeBlockEditor_CLASS_PREFIX + "toggle-scroll", function () { + return _this._toggleScroll(); + }); + this.on("click ." + popupCodeBlockEditor_CLASS_OK_BUTTON, function () { + return _this._save(); + }); + this.on("click ." + popupCodeBlockEditor_CLASS_CLOSE_BUTTON, function () { + return _this.hide(); + }); + this.on("click ." + popupCodeBlockEditor_CLASS_PREFIX + "close", function () { + return _this.hide(); + }); + this.on("click ." + popupCodeBlockEditor_CLASS_PREFIX + "editor-wrapper", function (ev) { + if (ev.target === _this._codeMirrorWrapper) { + _this._focusEditor(true); + } + }); + } + /** + * bind editor events + * @private + * @override + */ + ; + + _proto._initEditorEvent = function _initEditorEvent() { + var _this2 = this; + + _LayerPopup.prototype._initEditorEvent.call(this); + + this.eventManager.listen('openPopupCodeBlockEditor', function (codeBlockElement) { + _this2.eventManager.emit('closeAllPopup'); + + _this2.show(codeBlockElement); + + return _this2; + }); + this.eventManager.listen('closeAllPopup', this.hide.bind(this)); + this.eventManager.listen('closePopupCodeBlockEditor', this.hide.bind(this)); + }; + + _proto._createCodeBlockEditor = function _createCodeBlockEditor() { + var codeMirrorWrapper = document.createElement('div'); + codeMirrorWrapper.className = popupCodeBlockEditor_CLASS_PREFIX + "editor-wrapper"; + this._codeBlockEditor = new codeBlockEditor(codeMirrorWrapper, this.eventManager); + return codeMirrorWrapper; + }; + + _proto._createPreview = function _createPreview() { + var previewWrapper = document.createElement('div'); + this._codeBlockPreview = new codeBlockPreview(previewWrapper, this.eventManager, this.convertor, this._codeBlockEditor); + return previewWrapper; + }; + + _proto._createCodeBlockLanguagesCombo = function _createCodeBlockLanguagesCombo() { + var _this3 = this; + + var titleElement = this.getTitleElement(); + var codeBlockLanguagesCombo = new ui_codeBlockLanguagesCombo(this.eventManager, this.languages); + codeBlockLanguagesCombo.setOnLanguageSelected(function (selectedLanguage) { + _this3._codeBlockEditor.setLanguage(selectedLanguage); + + _this3._codeBlockEditor.refresh(); + + _this3._focusEditor(); + }); + titleElement.innerHTML = 'CodeBlock Editor'; + titleElement.appendChild(codeBlockLanguagesCombo.getElement()); + return codeBlockLanguagesCombo; + }; + + _proto._updateFitWindowButton = function _updateFitWindowButton() { + dom["a" /* default */].toggleClass(this._toggleFitButton, 'active', this.isFitToWindow()); + }; + + _proto._updatePreviewButton = function _updatePreviewButton() { + dom["a" /* default */].toggleClass(this._togglePreviewButton, 'active', this._scrollSyncSplit.isSplitView()); + }; + + _proto._updateScrollButton = function _updateScrollButton() { + if (this._scrollSyncSplit.isSplitView()) { + css_default()(this._toggleScrollButton, { + display: 'inline-block' + }); + } else { + css_default()(this._toggleScrollButton, { + display: 'none' + }); + } + + dom["a" /* default */].toggleClass(this._toggleScrollButton, 'active', this._scrollSyncSplit.isScrollSynced()); + }; + + _proto._focusEditor = function _focusEditor(cursorToEnd) { + this._codeBlockEditor.focus(); + + if (cursorToEnd) { + this._codeBlockEditor.moveCursorToEnd(); + } else { + this._codeBlockEditor.moveCursorToStart(); + } + }; + + _proto._togglePreview = function _togglePreview() { + this._scrollSyncSplit.toggleSplitView(); + + this._updatePreviewButton(); + + this._updateScrollButton(); + + this._codeBlockEditor.refresh(); + }; + + _proto._toggleFitToWindow = function _toggleFitToWindow() { + this.toggleFitToWindow(); + + this._updateFitWindowButton(); + + this._codeBlockEditor.refresh(); + }; + + _proto._toggleScroll = function _toggleScroll() { + this._scrollSyncSplit.toggleScrollSync(); + + this._updateScrollButton(); + } + /** + * store code mirror text to wysiwyg code block + * @private + */ + ; + + _proto._save = function _save() { + this._codeBlockEditor.save(this._codeBlockElement); + + this.hide(); + } + /** + * load code mirror text from wysiwyg code block + * @param {HTMLElement} codeBlockElement - code block element instance to load code from + * @private + */ + ; + + _proto._load = function _load(codeBlockElement) { + this._codeBlockElement = codeBlockElement; + + this._codeBlockEditor.load(codeBlockElement); + + this._codeBlockLanguagesCombo.setLanguage(this._codeBlockEditor.getLanguage()); + + this._focusEditor(); + + this._codeBlockPreview.refresh(); + } + /** + * show popup + * @param {HTMLElement} codeBlockElement - code block element + * @override + */ + ; + + _proto.show = function show(codeBlockElement) { + _LayerPopup.prototype.show.call(this); + + if (!codeBlockElement) { + throw new Error('should be called with codeBlockElement'); + } + + this._load(codeBlockElement); + } + /** + * hide popup + * @override + */ + ; + + _proto.hide = function hide() { + this.setFitToWindow(false); + + if (this._codeBlockEditor) { + this._codeBlockEditor.clear(); + } + + if (this._codeBlockPreview) { + this._codeBlockPreview.clear(); + } + + this._codeBlockElement = null; + + _LayerPopup.prototype.hide.call(this); + }; + + return PopupCodeBlockEditor; +}(layerpopup); + +/* harmony default export */ var popupCodeBlockEditor = (popupCodeBlockEditor_PopupCodeBlockEditor); +// CONCATENATED MODULE: ./src/js/ui/defaultUI.js +function defaultUI_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @fileoverview default UI + * @author NHN FE Development Lab + */ + + + + + + + + + + + + + + + + + +var CLASS_TOOLBAR = 'te-toolbar-section'; +var CLASS_MARKDOWN_TAB = 'te-markdown-tab-section'; +var CLASS_EDITOR = 'te-editor-section'; +var CLASS_MODE_SWITCH = 'te-mode-switch-section'; +var CONTAINER_TEMPLATE = ['
    ', "
    ", "
    ", "
    ", '
    '].join(''); +/** + * Class DefaultUI + * @param {ToastUIEditor} editor - editor instance + */ + +var defaultUI_DefaultUI = /*#__PURE__*/function () { + /** + * UI name + * @type {string} + */ + + /** + * DefaultToolbar wrapper element + * @type {HTMLElement} + */ + + /** + * DefaultToolbar instance + * @type {DefaultToolbar} + * @private + */ + + /** + * @type {HTMLElement} + * @private + */ + + /** + * editor section element + * @private + * @type {HTMLElement} + */ + + /** + * editor type ww/md + * @private + * @type {string} + */ + + /** + * editor instance + * @private + * @type {ToastUIEditor} + */ + + /** + * markdown tab section element + * @private + * @type {HTMLElement} + */ + + /** + * markdown tab + * @private + * @type {Tab} + */ + + /** + * mode switch instance + * @private + * @type {ModeSwitch} + */ + + /** + * popup instances + * @private + * @type {Array} + */ + function DefaultUI(editor) { + defaultUI_defineProperty(this, "name", 'default'); + + defaultUI_defineProperty(this, "el", void 0); + + defaultUI_defineProperty(this, "_toolbar", void 0); + + defaultUI_defineProperty(this, "_container", void 0); + + defaultUI_defineProperty(this, "_editorSection", void 0); + + defaultUI_defineProperty(this, "_initialEditType", void 0); + + defaultUI_defineProperty(this, "_editor", void 0); + + defaultUI_defineProperty(this, "_markdownTabSection", void 0); + + defaultUI_defineProperty(this, "_markdownTab", void 0); + + defaultUI_defineProperty(this, "_modeSwitch", void 0); + + defaultUI_defineProperty(this, "_popups", []); + + this._editor = editor; + this._initialEditType = editor.options.initialEditType; + + this._init(editor.options); + + this._initEvent(); + } + + var _proto = DefaultUI.prototype; + + _proto._init = function _init(_ref) { + var container = _ref.el, + toolbarItems = _ref.toolbarItems, + hideModeSwitch = _ref.hideModeSwitch; + this.el = dom["a" /* default */].createElementWith(CONTAINER_TEMPLATE, container); + this._container = container; + this._editorSection = this.el.querySelector("." + CLASS_EDITOR); + + this._editorSection.appendChild(this._editor.layout.getEditorEl()); + + this._initToolbar(this._editor.eventManager, toolbarItems); + + this._initModeSwitch(this._editor.eventManager, hideModeSwitch); + + this._initPopupAddLink(); + + this._initPopupAddImage(); + + this._initPopupAddTable(); + + this._initPopupAddHeading(); + + this._initPopupTableUtils(); + + this._initPopupCodeBlockLanguages(); + + this._initPopupCodeBlockEditor(); + + this._initMarkdownTab(); + }; + + _proto._initEvent = function _initEvent() { + this._editor.eventManager.listen('hide', this.hide.bind(this)); + + this._editor.eventManager.listen('show', this.show.bind(this)); + + this._editor.eventManager.listen('changeMode', this._markdownTabControl.bind(this)); + + this._editor.eventManager.listen('changePreviewStyle', this._markdownTabControl.bind(this)); + }; + + _proto._initToolbar = function _initToolbar(eventManager, toolbarItems) { + var toolbar = new defaultToolbar(eventManager, toolbarItems); + this._toolbar = toolbar; + this.el.querySelector("." + CLASS_TOOLBAR).appendChild(toolbar.el); + }; + + _proto._initModeSwitch = function _initModeSwitch(eventManager, hideModeSwitch) { + var _this = this; + + var modeSwitchTabBar = this.el.querySelector("." + CLASS_MODE_SWITCH); + var editType = this._initialEditType === 'markdown' ? ui_modeSwitch.TYPE.MARKDOWN : ui_modeSwitch.TYPE.WYSIWYG; + var modeSwitch = new ui_modeSwitch(modeSwitchTabBar, editType, eventManager); + this._modeSwitch = modeSwitch; + + if (hideModeSwitch) { + modeSwitch.hide(); + } + + modeSwitch.on('modeSwitched', function (type) { + return _this._editor.changeMode(type); + }); + }; + + _proto._initMarkdownTab = function _initMarkdownTab() { + var editor = this._editor; + this._markdownTab = new tab({ + initName: i18n.get('Write'), + items: [i18n.get('Write'), i18n.get('Preview')], + sections: [editor.layout.getMdEditorContainerEl(), editor.layout.getPreviewEl()] + }); + this._markdownTabSection = this.el.querySelector("." + CLASS_MARKDOWN_TAB); + + this._markdownTabSection.appendChild(this._markdownTab.el); + + this._markdownTab.on('itemClick', function (itemText) { + if (itemText === i18n.get('Preview')) { + editor.eventManager.emit('previewNeedsRefresh'); + editor.eventManager.emit('changePreviewTabPreview'); + editor.eventManager.emit('closeAllPopup'); + } else { + editor.getCodeMirror().focus(); + editor.eventManager.emit('changePreviewTabWrite'); + } + }); + }; + + _proto._markdownTabControl = function _markdownTabControl() { + if (this._editor.isMarkdownMode() && this._editor.getCurrentPreviewStyle() === 'tab') { + css_default()(this._markdownTabSection, { + display: 'block' + }); + + this._markdownTab.activate(i18n.get('Write')); + } else { + css_default()(this._markdownTabSection, { + display: 'none' + }); + } + }; + + _proto._initPopupAddLink = function _initPopupAddLink() { + this._popups.push(new popupAddLink({ + target: this.el, + editor: this._editor + })); + }; + + _proto._initPopupAddImage = function _initPopupAddImage() { + this._popups.push(new popupAddImage({ + target: this.el, + eventManager: this._editor.eventManager + })); + }; + + _proto._initPopupAddTable = function _initPopupAddTable() { + this._popups.push(new popupAddTable({ + target: this._toolbar.el, + eventManager: this._editor.eventManager, + button: this.el.querySelector('button.tui-table'), + css: { + position: 'absolute' + } + })); + }; + + _proto._initPopupAddHeading = function _initPopupAddHeading() { + this._popups.push(new popupAddHeading({ + target: this._toolbar.el, + eventManager: this._editor.eventManager, + button: this.el.querySelector('button.tui-heading'), + css: { + position: 'absolute' + } + })); + }; + + _proto._initPopupTableUtils = function _initPopupTableUtils() { + var _this2 = this; + + this._editor.eventManager.listen('contextmenu', function (ev) { + if (dom["a" /* default */].parents(ev.data.target, '[contenteditable=true] table').length > 0) { + ev.data.preventDefault(); + + _this2._editor.eventManager.emit('openPopupTableUtils', ev.data); + } + }); + + this._popups.push(new popupTableUtils({ + target: this.el, + eventManager: this._editor.eventManager + })); + }; + + _proto._initPopupCodeBlockLanguages = function _initPopupCodeBlockLanguages() { + var editor = this._editor; + + this._popups.push(new popupCodeBlockLanguages({ + target: this.el, + eventManager: editor.eventManager, + languages: editor.codeBlockLanguages + })); + }; + + _proto._initPopupCodeBlockEditor = function _initPopupCodeBlockEditor() { + this._popups.push(new popupCodeBlockEditor({ + target: this.el, + eventManager: this._editor.eventManager, + convertor: this._editor.convertor, + languages: this._editor.codeBlockLanguages + })); + } + /** + * get toolbar instance + * @returns {Toolbar} - toolbar instance + */ + ; + + _proto.getToolbar = function getToolbar() { + return this._toolbar; + } + /** + * set toolbar instance + * @param {Toolbar} toolbar - toolbar + */ + ; + + _proto.setToolbar = function setToolbar(toolbar) { + this._toolbar.destroy(); + + this._toolbar = toolbar; + } + /** + * get mode switch instance + * @returns {ModeSwitch} - mode switch instance + */ + ; + + _proto.getModeSwitch = function getModeSwitch() { + return this._modeSwitch; + } + /** + * get editor section height + * @returns {Number} - height of editor section + */ + ; + + _proto.getEditorSectionHeight = function getEditorSectionHeight() { + var clientRect = this._editorSection.getBoundingClientRect(); + + return clientRect.bottom - clientRect.top; + } + /** + * get editor height + * @returns {Number} - height of editor + */ + ; + + _proto.getEditorHeight = function getEditorHeight() { + var clientRect = this._container.getBoundingClientRect(); + + return clientRect.bottom - clientRect.top; + } + /** + * get Table Popup + * @returns {PopupTableUtils} - PopupTableUtils + */ + ; + + _proto.getPopupTableUtils = function getPopupTableUtils() { + var tablePopup; + + this._popups.forEach(function (popup) { + if (popup instanceof popupTableUtils) { + tablePopup = popup; + } + }); + + return tablePopup; + } + /** + * hide + */ + ; + + _proto.hide = function hide() { + addClass_default()(this.el, 'te-hide'); + } + /** + * show + */ + ; + + _proto.show = function show() { + removeClass_default()(this.el, 'te-hide'); + } + /** + * remove + */ + ; + + _proto.remove = function remove() { + dom["a" /* default */].remove(this.el); + + this._markdownTab.remove(); + + this._modeSwitch.remove(); + + this._toolbar.destroy(); + + this._popups.forEach(function (popup) { + return popup.remove(); + }); + + this._popups = []; + tooltip.hide(); + } + /** + * creates popup + * @param {LayerPopupOption} options - layerPopup options + * @returns {LayerPopup} - crated layerPopup + */ + ; + + _proto.createPopup = function createPopup(options) { + return new layerpopup(options); + }; + + return DefaultUI; +}(); + +/* harmony default export */ var defaultUI = (defaultUI_DefaultUI); +// EXTERNAL MODULE: ./src/js/codeBlockManager.js +var codeBlockManager = __webpack_require__(30); + +// EXTERNAL MODULE: /Users/nhn/project/tui.editor/libs/to-mark/dist/to-mark.js +var to_mark = __webpack_require__(32); +var to_mark_default = /*#__PURE__*/__webpack_require__.n(to_mark); + +// CONCATENATED MODULE: ./src/js/toMarkRenderer.js + + +/** + * Check if given node is valid delimiter run. + * According to common-mark spec, following examples are not valid delimiter runs. + * 1. opening (*|**) preceded by an alphanumeric and followed by a punctuation. + * (ex: a**~~c~~b**) + * 2. closing (*|**) preceded by a punctuation and followed by an alphanumeric. + * (ex: **b~~c~~**a) + * @see {@link https://spec.commonmark.org/0.29/#delimiter-run} + * @see {@link https://github.com/commonmark/commonmark-spec/issues/611#issuecomment-533578503} + */ + +function isValidDelimiterRun(node) { + var isElemNode = dom["a" /* default */].isElemNode, + isTextNode = dom["a" /* default */].isTextNode; + var isInvalidOpener = isTextNode(node.previousSibling) && isElemNode(node.firstChild); + var isInvalidCloser = isTextNode(node.nextSibling) && isElemNode(node.lastChild); + return !isInvalidOpener && !isInvalidCloser; +} + +function convertEmphasis(node, subContent, delimiter) { + var FIND_BEFORE_AND_AFTER_SPACES_RX = /^(\s*)((?:.|\n)*\S)(\s*)$/m; + + var _subContent$match = subContent.match(FIND_BEFORE_AND_AFTER_SPACES_RX), + beforeSpaces = _subContent$match[1], + trimmedContent = _subContent$match[2], + afterSpaces = _subContent$match[3]; + + var convertedContent; + + if (isValidDelimiterRun(node)) { + convertedContent = "" + delimiter + trimmedContent + delimiter; + } else { + var tagName = node.nodeName.toLowerCase(); + convertedContent = "<" + tagName + ">" + trimmedContent + ""; + } + + return "" + beforeSpaces + convertedContent + afterSpaces; +} + +/* harmony default export */ var toMarkRenderer = (to_mark_default.a.Renderer.factory(to_mark_default.a.gfmRenderer, { + 'EM, I': function EMI(node, subContent) { + if (this.isEmptyText(subContent)) { + return ''; + } + + return convertEmphasis(node, subContent, '*'); + }, + 'STRONG, B': function STRONGB(node, subContent) { + if (this.isEmptyText(subContent)) { + return ''; + } + + return convertEmphasis(node, subContent, '**'); + }, + 'DEL, S': function DELS(node, subContent) { + if (this.isEmptyText(subContent)) { + return ''; + } + + return convertEmphasis(node, subContent, '~~'); + } +})); +// EXTERNAL MODULE: ./src/js/pluginHelper.js +var pluginHelper = __webpack_require__(31); + +// CONCATENATED MODULE: ./src/js/markdownCommands/emphasisCommon.js +/** + * @fileoverview This file is common logic for italic, bold, strike makrdown commands. + * @author NHN FE Development Lab + */ + +/** + * range expand according to expendSize + * If can not expand, return null + * @param {range} range - range + * @param {number} expendSize - expendSize + * @returns {object} expanded range or null + * @ignore + */ +var getExpandedRange = function getExpandedRange(range, expendSize) { + var start = range.start, + end = range.end; + var expendRange; + + if (start.ch >= expendSize) { + var from = { + line: start.line, + ch: start.ch - expendSize + }; + var to = { + line: end.line, + ch: end.ch + expendSize + }; + expendRange = { + from: from, + to: to + }; + } + + return expendRange; +}; +/** + * remove symbol in the front and back of text + * @param {string} text - text + * @param {string} symbol - text + * @returns {string} + * @ignore + */ + + +var removeSyntax = function removeSyntax(text, symbol) { + var symbolLength = symbol.length; + return text.substr(symbolLength, text.length - symbolLength * 2); +}; +/** + * append symbol in the front and back of text + * @param {string} text - text + * @param {string} symbol - text + * @returns {string} + * @ignore + */ + +var appendSyntax = function appendSyntax(text, symbol) { + return "" + symbol + text + symbol; +}; +/** + * check expanded text and replace text using replacer + * @param {CodeMirror.doc} doc - doc of codemirror + * @param {range} range - origin range + * @param {number} expandSize - expandSize + * @param {function} checker - sytax check function + * @param {function} replacer - text replace function + * @returns {boolean} - if replace text, return true. + * @ignore + */ + +var expandReplace = function expandReplace(doc, range, expandSize, checker, replacer) { + var expendRange = getExpandedRange(range, expandSize); + var result = false; + + if (expendRange) { + var from = expendRange.from, + to = expendRange.to; + var expendRangeText = doc.getRange(from, to); + + if (checker(expendRangeText)) { + doc.setSelection(from, to); + doc.replaceSelection(replacer(expendRangeText), 'around'); + result = true; + } + } + + return result; +}; +/** + * check text and replace text using replacer + * @param {CodeMirror.doc} doc - doc of codemirror + * @param {string} text - text + * @param {function} checker - sytax check function + * @param {function} replacer - text replace function + * @returns {boolean} - if replace text, return true. + * @ignore + */ + +var replace = function replace(doc, text, checker, replacer) { + var result = false; + + if (checker(text)) { + doc.replaceSelection(replacer(text), 'around'); + result = true; + } + + return result; +}; +var changeSyntax = function changeSyntax(doc, range, symbol, syntaxRegex, contentRegex) { + var _doc$getCursor = doc.getCursor(), + line = _doc$getCursor.line, + ch = _doc$getCursor.ch; + + var selectionStr = doc.getSelection(); + var symbolLength = symbol.length; + + var isSyntax = function isSyntax(t) { + return syntaxRegex.test(t); + }; // 1. expand text and check syntax => remove syntax + // 2. check text is syntax => remove syntax + // 3. If text does not match syntax, remove syntax inside text and then append syntax + + + if (!(expandReplace(doc, range, symbolLength, isSyntax, function (t) { + return removeSyntax(t, symbol); + }) || replace(doc, selectionStr, isSyntax, function (t) { + return removeSyntax(t, symbol); + }))) { + var removeSyntaxInsideText = selectionStr.replace(contentRegex, '$1'); + doc.replaceSelection(appendSyntax(removeSyntaxInsideText, symbol), 'around'); + } + + var afterSelectStr = doc.getSelection(); + var size = ch; + + if (!selectionStr) { + // If text was not selected, after replace text, move cursor + // For example **|** => | (move cusor -symbolLenth) + if (isSyntax(afterSelectStr)) { + size += symbolLength; + } else { + size -= symbolLength; + } + + doc.setCursor(line, size); + } +}; +// CONCATENATED MODULE: ./src/js/markdownCommands/bold.js +/** + * @fileoverview Implements Bold markdown command + * @author NHN FE Development Lab + */ + + +var boldRangeRegex = /^(\*{2}|_{2}).*\1$/; +var boldContentRegex = /[*_]{2,}([^*_]*)[*_]{2,}/g; +var boldSymbol = '**'; +/** + * Bold + * Add bold markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/Bold + * @ignore + */ + +var Bold = commandManager["a" /* default */].command('markdown', +/** @lends Bold */ +{ + name: 'Bold', + keyMap: ['CTRL+B', 'META+B'], + + /** + * Command Handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + var originRange = mde.getRange(); + changeSyntax(doc, originRange, boldSymbol, boldRangeRegex, boldContentRegex); + cm.focus(); + } +}); +/* harmony default export */ var bold = (Bold); +// CONCATENATED MODULE: ./src/js/markdownCommands/italic.js +/** + * @fileoverview Implements Italic markdown command + * @author NHN FE Development Lab + */ + + +var boldItalicRangeRegex = /^(\*{3}|_{3}).*\1$/; +var italic_boldRangeRegex = /^(\*{2}|_{2}).*\1$/; +var italicRangeRegex = /^(\*|_).*\1$/; +var italicContentRegex = /([^*_])[*_]([^*_]+)[*_]([^*_])/g; + +var isBoldItalic = function isBoldItalic(t) { + return boldItalicRangeRegex.test(t); +}; + +var isBold = function isBold(t) { + return italic_boldRangeRegex.test(t); +}; + +var isItalic = function isItalic(t) { + return italicRangeRegex.test(t); +}; + +var italicSymbol = '*'; +var italic_boldSymbol = '**'; +var boldItalicSymbol = '***'; +var italicLength = italicSymbol.length; +var boldLength = italic_boldSymbol.length; +var boldItalicLength = boldItalicSymbol.length; +/** + * remove italic syntax in the middle of given text + * @param {string} text - text selected + * @returns {string} - text eliminated all italic in the middle of it's content + * @ignore + */ + +var removeItalicInsideText = function removeItalicInsideText(text) { + return text ? text.replace(italicContentRegex, '$1$2$3') : ''; +}; + +var italic_replaceText = function replaceText(doc, text, range) { + // Check 3 cases when both text and expand text + // case 1 : bold & italic (when expand 3 both front and end) => remove italic + // case 2 : bold (when expand 2 both front and end) => append + // case 3 : italic (expand 1 both front and end) => remove + var expandReplaceBind = expandReplace.bind(this, doc, range); + return expandReplaceBind(boldItalicLength, isBoldItalic, function (t) { + return removeSyntax(t, italicSymbol); + }) || expandReplaceBind(boldLength, isBold, function (t) { + return appendSyntax(removeItalicInsideText(t), italicSymbol); + }) || expandReplaceBind(italicLength, isItalic, function (t) { + return removeSyntax(t, italicSymbol); + }) || replace(doc, text, isBoldItalic, function (t) { + return removeSyntax(t, italicSymbol); + }) || replace(doc, text, isBold, function (t) { + return appendSyntax(removeItalicInsideText(t), italicSymbol); + }) || replace(doc, text, isItalic, function (t) { + return removeSyntax(t, italicSymbol); + }); +}; + +var italic_replaceEmptyText = function replaceEmptyText(doc, range) { + // Check 3 cases when expand text + // case 1 : bold & italic => remove italic + // case 2 : bold => append + // case 3 : italic => remove + // if there is no match, make italic + return expandReplace(doc, range, boldItalicLength, isBoldItalic, function (t) { + return removeSyntax(t, italicSymbol); + }) || expandReplace(doc, range, boldLength, isBold, function (t) { + return appendSyntax(t, italicSymbol); + }) || expandReplace(doc, range, italicLength, isItalic, function () { + return ''; + }) || doc.replaceSelection("" + italicSymbol + italicSymbol, 'around'); +}; +/** + * Italic + * Add italic markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/Italic + * @ignore + */ + + +var Italic = commandManager["a" /* default */].command('markdown', +/** @lends Italic */ +{ + name: 'Italic', + keyMap: ['CTRL+I', 'META+I'], + + /** + * Command handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + + var _doc$getCursor = doc.getCursor(), + line = _doc$getCursor.line, + ch = _doc$getCursor.ch; + + var range = mde.getRange(); + var selectionStr = doc.getSelection(); + + if (selectionStr) { + // check selectionStr match bold & italic, bold, italic and then + // if there is no match, append italic + if (!italic_replaceText(doc, selectionStr, range)) { + // Before append italic, remove italic inside text and then append italic + // Example: One*Two*Three => *OneTwoThree* + doc.replaceSelection(appendSyntax(removeItalicInsideText(selectionStr), italicSymbol), 'around'); + } + } else { + italic_replaceEmptyText(doc, range); + var afterSelectStr = doc.getSelection(); + var size = ch; // If text was not selected, after replace text, move cursor + + if (isBoldItalic(afterSelectStr) || isItalic(afterSelectStr) && !isBold(afterSelectStr)) { + // For example **|** => ***|*** (move cusor +symbolLenth) + size += italicLength; + } else { + // For example *|* => | (move cusor -symbolLenth) + size -= italicLength; + } + + doc.setCursor(line, size); + } + + cm.focus(); + } +}); +/* harmony default export */ var italic = (Italic); +// CONCATENATED MODULE: ./src/js/markdownCommands/strike.js +/** + * @fileoverview Implements StrikeThrough markdown command + * @author NHN FE Development Lab + */ + + +var strikeRangeRegex = /^~~.*~~$/; +var strikeContentRegex = /~~([^~]*)~~/g; +var strikeSymbol = '~~'; +/** + * Strike + * Add strike markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/Strike + * @ignore + */ + +var Strike = commandManager["a" /* default */].command('markdown', +/** @lends Strike */ +{ + name: 'Strike', + keyMap: ['CTRL+S', 'META+S'], + + /** + * Command handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + var originRange = mde.getRange(); + changeSyntax(doc, originRange, strikeSymbol, strikeRangeRegex, strikeContentRegex); + cm.focus(); + } +}); +/* harmony default export */ var strike = (Strike); +// CONCATENATED MODULE: ./src/js/markdownCommands/blockquote.js +/** + * @fileoverview Implements Blockquote markdown command + * @author NHN FE Development Lab + */ + +var BlockquoteRegex = /^> ?/; +/** + * Blockquote + * Add blockquote markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/Blockquote + * @ignore + */ + +var Blockquote = commandManager["a" /* default */].command('markdown', +/** @lends Blockquote */ +{ + name: 'Blockquote', + keyMap: ['ALT+Q', 'ALT+Q'], + + /** + * command handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + var range = mde.getCurrentRange(); + var from = { + line: range.from.line, + ch: 0 + }; + var to = { + line: range.to.line, + ch: doc.getLineHandle(range.to.line).text.length + }; + var textToModify = doc.getRange(from, to); + var textLinesToModify = textToModify.split('\n'); + + var isNeedToRemove = this._haveBlockquote(textLinesToModify); + + var resultText; + + if (isNeedToRemove) { + resultText = this._removeBlockquote(textLinesToModify); + } else { + resultText = this._addBlockquote(textLinesToModify); + } + + doc.replaceRange(resultText.join('\n'), from, to); + + if (isNeedToRemove) { + var length = textLinesToModify.length; + + if (this._isBlockquoteWithSpace(textLinesToModify[length - 1])) { + range.to.ch -= 2; + } else { + range.to.ch -= 1; + } + } else { + range.to.ch += 2; + } + + doc.setCursor(range.to); + cm.focus(); + }, + + /** + * check all text in textArr starts with '>' + * @param {Array} textArr - text array + * @returns {boolean} - true if all text in textArr starts with '>' + * @private + */ + _haveBlockquote: function _haveBlockquote(textArr) { + for (var i = 0; i < textArr.length; i += 1) { + if (!BlockquoteRegex.test(textArr[i])) { + return false; + } + } + + return true; + }, + + /** + * add '> ' to all text in textArr + * @param {Array} textArr - text array + * @returns {Array} - new text array added '> ' + * @private + */ + _addBlockquote: function _addBlockquote(textArr) { + return textArr.map(function (text) { + return "> " + text; + }); + }, + + /** + * remove '> ' or '>' to all text in textArr + * @param {Array} textArr - text array + * @returns {Array} - new text array removed '> ' or '>' + * @private + */ + _removeBlockquote: function _removeBlockquote(textArr) { + return textArr.map(function (text) { + return text.replace(BlockquoteRegex, ''); + }); + }, + + /** + * check text start '> ' + * @param {string} text - text + * @returns {boolean} - if text start '> ', true + * @private + */ + _isBlockquoteWithSpace: function _isBlockquoteWithSpace(text) { + return /^> /.test(text); + } +}); +/* harmony default export */ var blockquote = (Blockquote); +// CONCATENATED MODULE: ./src/js/markdownCommands/heading.js +/** + * @fileoverview Implements Heading markdown command + * @author NHN FE Development Lab + */ + + +var heading_FIND_HEADING_RX = /^#+\s/g; +/** + * Heading + * Add heading markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/Heading + * @ignore + */ + +var Heading = commandManager["a" /* default */].command('markdown', +/** @lends Heading */ +{ + name: 'Heading', + + /** + * Command Handler + * @param {MarkdownEditor} mde MarkdownEditor instance + * @param {number} size heading size + */ + exec: function exec(mde, size) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + var range = mde.getCurrentRange(); + var from = { + line: range.from.line, + ch: 0 + }; + var to = { + line: range.to.line, + ch: doc.getLineHandle(range.to.line).text.length + }; + var lengthOfCurrentLineBefore = doc.getLine(to.line).length; + var textToModify = doc.getRange(from, to); + var textLinesToModify = textToModify.split('\n'); + toArray_default()(textLinesToModify).forEach(function (line, index) { + textLinesToModify[index] = getHeadingMarkdown(line, size); + }); + doc.replaceRange(textLinesToModify.join('\n'), from, to); + range.to.ch += doc.getLine(to.line).length - lengthOfCurrentLineBefore; + doc.setSelection(from, range.to); + cm.focus(); + } +}); +/** + * Get heading markdown + * @param {string} text Source test + * @param {number} size size + * @returns {string} + */ + +function getHeadingMarkdown(text, size) { + var foundedHeading = text.match(heading_FIND_HEADING_RX); + var heading = ''; + + do { + heading += '#'; + size -= 1; + } while (size > 0); + + if (foundedHeading) { + var _text$split = text.split(foundedHeading[0]); + + text = _text$split[1]; + } + + return heading + " " + text; +} + +/* harmony default export */ var markdownCommands_heading = (Heading); +// CONCATENATED MODULE: ./src/js/markdownCommands/paragraph.js +/** + * @fileoverview Implements Paragraph markdown command + * @author NHN FE Development Lab + */ + + +/** + * Paragraph + * Convert selected lines to paragraph + * @extends Command + * @module markdownCommands/Paragraph + * @ignore + */ + +var Paragraph = commandManager["a" /* default */].command('markdown', +/** @lends Paragraph */ +{ + name: 'Paragraph', + + /** + * Command Handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + var range = mde.getCurrentRange(); + var from = { + line: range.from.line, + ch: 0 + }; + var to = { + line: range.to.line, + ch: doc.getLineHandle(range.to.line).text.length + }; + var lengthOfCurrentLineBefore = doc.getLine(to.line).length; + var textToModify = doc.getRange(from, to); + var textLines = textToModify.split('\n'); + toArray_default()(textLines).forEach(function (line, index) { + textLines[index] = getParagraphMarkdown(line); + }); + doc.replaceRange(textLines.join('\n'), from, to); + range.to.ch += doc.getLine(to.line).length - lengthOfCurrentLineBefore; + doc.setSelection(from, to); + cm.focus(); + } +}); +/** + * Get paragraph markdown lineText + * @param {string} lineText line lineText + * @returns {string} + */ + +function getParagraphMarkdown(lineText) { + var headingRx = /^(#{1,6}| *((?:\*|-|\d\.)(?: \[[ xX]])?)) /; + return lineText.replace(headingRx, ''); +} + +/* harmony default export */ var paragraph = (Paragraph); +// CONCATENATED MODULE: ./src/js/markdownCommands/hr.js +/** + * @fileoverview Implements HR markdown command + * @author NHN FE Development Lab + */ + +/** + * HR + * Add HR markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/HR + * @ignore + */ + +var HR = commandManager["a" /* default */].command('markdown', +/** @lends HR */ +{ + name: 'HR', + keyMap: ['CTRL+L', 'META+L'], + + /** + * Command handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + var replaceText = ''; + var range = mde.getCurrentRange(); + var from = { + line: range.from.line, + ch: range.from.ch + }; + var to = { + line: range.to.line, + ch: range.to.ch + }; + + if (range.collapsed) { + replaceText = doc.getLine(from.line); + from.ch = 0; + to.ch = doc.getLineHandle(range.to.line).text.length; + } + + if (doc.getLine(from.line).length) { + replaceText += '\n\n* * *\n\n'; + } else { + replaceText += '\n* * *\n'; + } + + doc.replaceRange(replaceText, from, to); + cm.focus(); + } +}); +/* harmony default export */ var markdownCommands_hr = (HR); +// CONCATENATED MODULE: ./src/js/markdownCommands/addLink.js +/** + * @fileoverview Implements Addlink markdown command + * @author NHN FE Development Lab + */ + + +var addLink_decodeURIGraceful = importManager.decodeURIGraceful, + encodeMarkdownCharacters = importManager.encodeMarkdownCharacters; +var FIND_MARKDOWN_IMAGE_SYNTAX_RX = /!\[.*\]\(.*\)/g; +var FIND_ESCAPED_CHARS_RX = /\(|\)|\[|\]|<|>/g; + +function escapeLinkTextExceptImageSyntax(linkText) { + var imageSyntaxRanges = []; + var result = FIND_MARKDOWN_IMAGE_SYNTAX_RX.exec(linkText); + + while (result) { + var _result = result, + index = _result.index; + imageSyntaxRanges.push([index, index + result[0].length]); + result = FIND_MARKDOWN_IMAGE_SYNTAX_RX.exec(linkText); + } + + return linkText.replace(FIND_ESCAPED_CHARS_RX, function (matched, offset) { + var isDelimiter = imageSyntaxRanges.some(function (range) { + return offset > range[0] && offset < range[1]; + }); + return isDelimiter ? matched : "\\" + matched; + }); +} +/** + * AddLink + * Add link markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/AddLink + * @ignore + */ + + +var AddLink = commandManager["a" /* default */].command('markdown', +/** @lends AddLink */ +{ + name: 'AddLink', + + /** + * command handler for AddLink + * @param {MarkdownEditor} mde - MarkdownEditor instance + * @param {object} data - data for image + */ + exec: function exec(mde, data) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + var range = mde.getCurrentRange(); + var from = { + line: range.from.line, + ch: range.from.ch + }; + var to = { + line: range.to.line, + ch: range.to.ch + }; + var linkText = data.linkText, + url = data.url; + linkText = addLink_decodeURIGraceful(linkText); + linkText = escapeLinkTextExceptImageSyntax(linkText); + url = encodeMarkdownCharacters(url); + var replaceText = "[" + linkText + "](" + url + ")"; + doc.replaceRange(replaceText, from, to); + cm.focus(); + } +}); +/* harmony default export */ var addLink = (AddLink); +// CONCATENATED MODULE: ./src/js/markdownCommands/addImage.js +/** + * @fileoverview Implments AddImage markdown command + * @author NHN FE Development Lab + */ + + +var addImage_decodeURIGraceful = importManager.decodeURIGraceful, + addImage_encodeMarkdownCharacters = importManager.encodeMarkdownCharacters, + escapeMarkdownCharacters = importManager.escapeMarkdownCharacters; +/** + * AddImage + * Add Image markdown syntax to markdown Editor + * @extends Command + * @module markdownCommands/AddImage + * @ignore + */ + +var AddImage = commandManager["a" /* default */].command('markdown', +/** @lends AddImage */ +{ + name: 'AddImage', + + /** + * Command Handler + * @param {MarkdownEditor} mde MarkdownEditor instance + * @param {object} data data for image + */ + exec: function exec(mde, data) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + var range = mde.getCurrentRange(); + var from = { + line: range.from.line, + ch: range.from.ch + }; + var to = { + line: range.to.line, + ch: range.to.ch + }; + var altText = data.altText, + imageUrl = data.imageUrl; + altText = addImage_decodeURIGraceful(altText); + altText = escapeMarkdownCharacters(altText); + imageUrl = addImage_encodeMarkdownCharacters(imageUrl); + var replaceText = "![" + altText + "](" + imageUrl + ")"; + doc.replaceRange(replaceText, from, to, '+addImage'); + cm.focus(); + } +}); +/* harmony default export */ var addImage = (AddImage); +// CONCATENATED MODULE: ./src/js/markdownCommands/ul.js +/** + * @fileoverview Implements UL markdown command + * @author NHN FE Development Lab + */ + +/** + * UL + * Add unordered list markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/UL + * @ignore + */ + +var UL = commandManager["a" /* default */].command('markdown', +/** @lends UL */ +{ + name: 'UL', + keyMap: ['CTRL+U', 'META+U'], + + /** + * Command handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var range = mde.getCurrentRange(); + var listManager = mde.componentManager.getManager('list'); + listManager.changeSyntax(range, 'ul'); + } +}); +/* harmony default export */ var markdownCommands_ul = (UL); +// CONCATENATED MODULE: ./src/js/markdownCommands/ol.js +/** + * @fileoverview Implements OL markdown command + * @author NHN FE Development Lab + */ + +/** + * OL + * Add ordered list markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/OL + * @ignore + */ + +var OL = commandManager["a" /* default */].command('markdown', +/** @lends OL */ +{ + name: 'OL', + keyMap: ['CTRL+O', 'META+O'], + + /** + * Command handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var range = mde.getCurrentRange(); + var listManager = mde.componentManager.getManager('list'); + listManager.changeSyntax(range, 'ol'); + } +}); +/* harmony default export */ var ol = (OL); +// CONCATENATED MODULE: ./src/js/markdownCommands/indent.js +/** + * @fileoverview Implements Indent markdown command + * @author NHN FE Development Lab + */ + +/** + * Indent + * Add Indent markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/inent + * @ignore + */ + +var Indent = commandManager["a" /* default */].command('markdown', +/** @lends Indent */ +{ + name: 'Indent', + + /** + * Command handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var cm = mde.getEditor(); + cm.execCommand('indentOrderedList'); + } +}); +/* harmony default export */ var markdownCommands_indent = (Indent); +// CONCATENATED MODULE: ./src/js/markdownCommands/outdent.js +/** + * @fileoverview Implements Outdent markdown command + * @author NHN FE Development Lab + */ + +/** + * Outdent + * Add Outdent markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/outdent + * @ignore + */ + +var Outdent = commandManager["a" /* default */].command('markdown', +/** @lends Outdent */ +{ + name: 'Outdent', + + /** + * Command handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var cm = mde.getEditor(); + cm.execCommand('indentLessOrderedList'); + } +}); +/* harmony default export */ var outdent = (Outdent); +// CONCATENATED MODULE: ./src/js/markdownCommands/table.js +/** + * @fileoverview Implements Table markdown command + * @author NHN FE Development Lab + */ + +/** + * Table + * Add table markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/Table + * @ignore + */ + +var Table = commandManager["a" /* default */].command('markdown', +/** @lends Table */ +{ + name: 'Table', + + /** + * Command handler + * @param {MarkdownEditor} mde MarkdownEditor instance + * @param {number} col column count + * @param {number} row row count + * @param {Array} data initial table data + */ + exec: function exec(mde, col, row, data) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + var table = '\n'; + + if (cm.getCursor().ch > 0) { + table += '\n'; + } + + table += makeHeader(col, data); + table += makeBody(col, row - 1, data); + doc.replaceSelection(table); + + if (!data) { + cm.setCursor(cm.getCursor().line - row, 2); + } + + mde.focus(); + } +}); +/** + * makeHeader + * make table header markdown string + * @param {number} col Column count + * @param {array} data Cell's text content + * @returns {string} markdown string + */ + +function makeHeader(col, data) { + var header = '|'; + var border = '|'; + var index = 0; + + while (col) { + if (data) { + header += " " + data[index] + " |"; + index += 1; + } else { + header += ' |'; + } + + border += ' --- |'; + col -= 1; + } + + return header + "\n" + border + "\n"; +} +/** + * makeBody + * make table body markdown string + * @param {number} col column count + * @param {number} row row count + * @param {Array} data initial table data + * @returns {string} html string + */ + + +function makeBody(col, row, data) { + var body = ''; + var index = col; + + for (var irow = 0; irow < row; irow += 1) { + body += '|'; + + for (var icol = 0; icol < col; icol += 1) { + if (data) { + body += " " + data[index] + " |"; + index += 1; + } else { + body += ' |'; + } + } + + body += '\n'; + } + + body = body.replace(/\n$/g, ''); + return body; +} + +/* harmony default export */ var markdownCommands_table = (Table); +// CONCATENATED MODULE: ./src/js/markdownCommands/task.js +/** + * @fileoverview Implements Task markdown command + * @author NHN FE Development Lab + */ + +/** + * Task + * @extends Command + * @module markdownCommands/Task + * @ignore + */ + +var Task = commandManager["a" /* default */].command('markdown', +/** @lends Task */ +{ + name: 'Task', + keyMap: ['ALT+T', 'ALT+T'], + + /** + * Command handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var range = mde.getCurrentRange(); + var listManager = mde.componentManager.getManager('list'); + listManager.changeSyntax(range, 'task'); + } +}); +/* harmony default export */ var markdownCommands_task = (Task); +// CONCATENATED MODULE: ./src/js/markdownCommands/code.js +/** + * @fileoverview Implements Code markdown command + * @author NHN FE Development Lab + */ + +var codeRangeRegex = /^`([^`]+)`$/; +var codeContentRegex = /`([^`]+)`/g; +/** + * Code + * Add code markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/Code + * @ignore + */ + +var Code = commandManager["a" /* default */].command('markdown', +/** @lends Code */ +{ + name: 'Code', + keyMap: ['SHIFT+CTRL+C', 'SHIFT+META+C'], + + /** + * Command Handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + var selection = doc.getSelection(); + var cursor = cm.getCursor(); + var hasSyntax = this.hasStrikeSyntax(selection); + var result; + + if (hasSyntax) { + result = this.remove(selection); + result = this._removeCodeSyntax(result); + } else { + result = this._removeCodeSyntax(selection); + result = this.append(result); + } + + doc.replaceSelection(result, 'around'); + + if (!selection && !hasSyntax) { + this.setCursorToCenter(doc, cursor, hasSyntax); + } + + cm.focus(); + }, + + /** + * set cursor to center + * @param {CodeMirror.doc} doc - codemirror document + * @param {object} cursor - codemirror cursor + * @param {boolean} isRemoved - whether it involes deletion + */ + setCursorToCenter: function setCursorToCenter(doc, cursor, isRemoved) { + var pos = isRemoved ? -1 : 1; + doc.setCursor(cursor.line, cursor.ch + pos); + }, + + /** + * has code syntax + * @param {string} text Source text + * @returns {boolean} true if the given text has a code syntax + */ + hasStrikeSyntax: function hasStrikeSyntax(text) { + return codeRangeRegex.test(text); + }, + + /** + * apply Code + * @param {string} text - selected text + * @returns {string} - text after code syntax applied + */ + append: function append(text) { + return "`" + text + "`"; + }, + + /** + * remove Code + * @param {string} text - selected text + * @returns {string} - text after code syntax removed + */ + remove: function remove(text) { + return text.substr(1, text.length - 2); + }, + + /** + * remove bold syntax in the middle of given text + * @param {string} text - text selected + * @returns {string} - text eliminated all code in the middle of it's content + * @private + */ + _removeCodeSyntax: function _removeCodeSyntax(text) { + return text ? text.replace(codeContentRegex, '$1') : ''; + } +}); +/* harmony default export */ var markdownCommands_code = (Code); +// CONCATENATED MODULE: ./src/js/markdownCommands/codeBlock.js +/** + * @fileoverview Implements CodeBlock markdown command + * @author NHN FE Development Lab + */ + +/** + * CodeBlock + * Add CodeBlock markdown syntax to markdown editor + * @extends Command + * @module markdownCommands/CodeBlock + * @ignore + */ + +var CodeBlock = commandManager["a" /* default */].command('markdown', +/** @lends CodeBlock */ +{ + name: 'CodeBlock', + keyMap: ['SHIFT+CTRL+P', 'SHIFT+META+P'], + + /** + * Command handler + * @param {MarkdownEditor} mde MarkdownEditor instance + */ + exec: function exec(mde) { + var cm = mde.getEditor(); + var doc = cm.getDoc(); + var range = mde.getCurrentRange(); + var replaceText = ['```', doc.getSelection(), '```']; + var cursorOffset = 1; // insert a line break to the front if the selection starts in the middle of a text + + if (range.from.ch !== 0) { + replaceText.unshift(''); + cursorOffset += 1; + } // insert a line break to the end if the selection has trailing text + + + if (range.to.ch !== doc.getLine(range.to.line).length) { + replaceText.push(''); + } + + doc.replaceSelection(replaceText.join('\n')); + cm.setCursor(range.from.line + cursorOffset, 0); + cm.focus(); + } +}); +/* harmony default export */ var markdownCommands_codeBlock = (CodeBlock); +// CONCATENATED MODULE: ./src/js/markdownCommands/changeTaskMarker.js +/** + * @fileoverview Implements ChangeTaskMarker markdown command + * @author NHN FE Development Lab + */ + + +var TASK_MARKER_RX = /^\[(\s*)(x?)(\s*)\](?:\s+)/i; +/** + * Add ChangeTaskMarker command + * @extends Command + * @module markdownCommands/ToggleTaskMarker + * @ignore + */ + +var ChangeTaskMarker = commandManager["a" /* default */].command('markdown', +/** @lends ChangeTaskMarker */ +{ + name: 'ChangeTaskMarker', + exec: function exec(mde) { + var cm = mde.getEditor(); + + var _cm$getCursor = cm.getCursor(), + line = _cm$getCursor.line, + ch = _cm$getCursor.ch; + + var mdCh = cm.getLine(line).length === ch ? ch : ch + 1; + var mdNode = mde.getToastMark().findNodeAtPosition([line + 1, mdCh]); + var paraNode = Object(markdown["b" /* findClosestNode */])(mdNode, function (node) { + return node.type === 'paragraph' && node.parent && node.parent.type === 'item'; + }); + + if (paraNode && paraNode.firstChild) { + var _paraNode$firstChild = paraNode.firstChild, + literal = _paraNode$firstChild.literal, + sourcepos = _paraNode$firstChild.sourcepos; + var _sourcepos$ = sourcepos[0], + startLine = _sourcepos$[0], + startCh = _sourcepos$[1]; + var matched = literal.match(TASK_MARKER_RX); + + if (matched) { + var startSpaces = matched[1], + stateChar = matched[2], + lastSpaces = matched[3]; + var spaces = startSpaces.length + lastSpaces.length; + var startPos = { + line: startLine - 1, + ch: startCh + }; + + if (stateChar) { + cm.replaceRange(stateChar, startPos, Object(markdown["a" /* addChPos */])(startPos, spaces ? spaces + 1 : 0)); + } else if (!spaces) { + cm.replaceRange(' ', startPos, startPos); + } + } + } + } +}); +/* harmony default export */ var changeTaskMarker = (ChangeTaskMarker); +// CONCATENATED MODULE: ./src/js/markdownCommands/toggleTaskMarker.js +/** + * @fileoverview Implements ToggleTaskMarker markdown command + * @author NHN FE Development Lab + */ + + +/** + * Add ToggleTaskMarker command + * @extends Command + * @module markdownCommands/ToggleTaskMarker + * @ignore + */ + +var ToggleTaskMarker = commandManager["a" /* default */].command('markdown', +/** @lends ToggleTaskMarker */ +{ + name: 'ToggleTaskMarker', + exec: function exec(mde) { + var _this = this; + + var cm = mde.getEditor(); + var ranges = cm.listSelections(); + ranges.forEach(function (range) { + var anchor = range.anchor, + head = range.head; + var startLine = Math.min(anchor.line, head.line); + var endLine = Math.max(anchor.line, head.line); + var mdNode; + + for (var index = startLine, len = endLine; index <= len; index += 1) { + mdNode = mde.getToastMark().findFirstNodeAtLine(index + 1); + + if (mdNode.type === 'list' || mdNode.type === 'item') { + _this._changeTaskState(mdNode, index, cm); + } + } + }); + }, + _changeTaskState: function _changeTaskState(list, line, cm) { + var listData = list.listData, + sourcepos = list.sourcepos; + var task = listData.task, + checked = listData.checked, + padding = listData.padding; + + if (task) { + var stateChar = checked ? ' ' : 'x'; + var _sourcepos$ = sourcepos[0], + startCh = _sourcepos$[1]; + var startPos = { + line: line, + ch: startCh + padding + }; + cm.replaceRange(stateChar, startPos, Object(markdown["a" /* addChPos */])(startPos, 1)); + } + } +}); +/* harmony default export */ var toggleTaskMarker = (ToggleTaskMarker); +// CONCATENATED MODULE: ./src/js/markdownCommands/moveNextCursorOrIndent.js +/** + * @fileoverview Implements MoveNextCursorOrIndent markdown command + * @author NHN FE Development Lab + */ + + +/** + * Add MoveNextCursorOrIndent command + * @extends Command + * @module markdownCommands/MoveNextCursorOrIndent + * @ignore + */ + +var MoveNextCursorOrIndent = commandManager["a" /* default */].command('markdown', +/** @lends MoveNextCursorOrIndent */ +{ + name: 'MoveNextCursorOrIndent', + exec: function exec(mde) { + var cm = mde.getEditor(); + + var _cm$getCursor = cm.getCursor(), + line = _cm$getCursor.line, + ch = _cm$getCursor.ch; + + var mdCh = cm.getLine(line).length === ch ? ch : ch + 1; + var mdNode = mde.getToastMark().findNodeAtPosition([line + 1, mdCh]); + var cellNode = Object(markdown["b" /* findClosestNode */])(mdNode, function (node) { + return Object(markdown["l" /* isTableCellNode */])(node); + }); + + if (cellNode) { + this._moveCursorNextCell(cellNode, cm); + } else { + cm.execCommand('indentOrderedList'); + } + }, + _moveCursorNextCell: function _moveCursorNextCell(cell, cm) { + var next = cell.next, + parent = cell.parent; + var line = Object(markdown["f" /* getMdStartLine */])(cell); + var ch = Object(markdown["c" /* getMdEndCh */])(cell) + 2; + + if (next) { + ch = Object(markdown["c" /* getMdEndCh */])(next); + } else { + var nextRow = !parent.next && parent.parent.type === 'tableHead' ? parent.parent.next.firstChild : parent.next; + + if (nextRow) { + line = line + 1; + ch = Object(markdown["c" /* getMdEndCh */])(nextRow.firstChild); + } + } + + cm.setCursor({ + line: line - 1, + ch: ch - 1 + }); + } +}); +/* harmony default export */ var moveNextCursorOrIndent = (MoveNextCursorOrIndent); +// CONCATENATED MODULE: ./src/js/markdownCommands/movePrevCursorOrOutdent.js +/** + * @fileoverview Implements MoveCursorOrOutdent markdown command + * @author NHN FE Development Lab + */ + + +/** + * Add MovePrevCursorOrOutdent command + * @extends Command + * @module markdownCommands/MovePrevCursorOrOutdent + * @ignore + */ + +var MovePrevCursorOrOutdent = commandManager["a" /* default */].command('markdown', +/** @lends MovePrevCursorOrOutdent */ +{ + name: 'MovePrevCursorOrOutdent', + exec: function exec(mde) { + var cm = mde.getEditor(); + + var _cm$getCursor = cm.getCursor(), + line = _cm$getCursor.line, + ch = _cm$getCursor.ch; + + var mdCh = cm.getLine(line).length === ch ? ch : ch + 1; + var mdNode = mde.getToastMark().findNodeAtPosition([line + 1, mdCh]); + var cellNode = Object(markdown["b" /* findClosestNode */])(mdNode, function (node) { + return Object(markdown["l" /* isTableCellNode */])(node); + }); + + if (cellNode) { + this._moveCursorPrevCell(cellNode, cm); + } else { + cm.execCommand('indentLessOrderedList'); + } + }, + _moveCursorPrevCell: function _moveCursorPrevCell(cell, cm) { + var prev = cell.prev, + parent = cell.parent; + var line = Object(markdown["f" /* getMdStartLine */])(cell); + var ch = 1; + + if (prev) { + ch = Object(markdown["c" /* getMdEndCh */])(prev); + } else { + var prevRow = !parent.prev && parent.parent.type === 'tableBody' ? parent.parent.prev.lastChild : parent.prev; + + if (prevRow) { + line = line - 1; + ch = Object(markdown["c" /* getMdEndCh */])(prevRow.lastChild); + } + } + + cm.setCursor({ + line: line - 1, + ch: ch - 1 + }); + } +}); +/* harmony default export */ var movePrevCursorOrOutdent = (MovePrevCursorOrOutdent); +// CONCATENATED MODULE: ./src/js/markdownCommands/addLine.js +/** + * @fileoverview Implements AddLine markdown command + * @author NHN FE Development Lab + */ + + + +function createTableRow(row) { + var columnLen = row.parent.parent.columns.length; + var result = '|'; + + for (var i = 0; i < columnLen; i += 1) { + result += ' |'; + } + + return result; +} +/** + * Add AddLine command + * @extends Command + * @module markdownCommands/AddLine + * @ignore + */ + + +var AddLine = commandManager["a" /* default */].command('markdown', +/** @lends AddLine */ +{ + name: 'AddLine', + exec: function exec(mde) { + var cm = mde.getEditor(); + + var _cm$getCursor = cm.getCursor(), + line = _cm$getCursor.line, + ch = _cm$getCursor.ch; + + var mdCh = cm.getLine(line).length === ch ? ch : ch + 1; + var mdNode = mde.getToastMark().findNodeAtPosition([line + 1, mdCh]); + var cellNode = Object(markdown["b" /* findClosestNode */])(mdNode, function (node) { + return Object(markdown["l" /* isTableCellNode */])(node) && (node.parent.type === 'tableDelimRow' || node.parent.parent.type === 'tableBody'); + }); + + if (cellNode) { + this._addTableRowByCell(cellNode, cm); + } else { + cm.execCommand('newlineAndIndentContinueMarkdownList'); + } + }, + _addTableRowByCell: function _addTableRowByCell(cell, cm) { + var line = Object(markdown["f" /* getMdStartLine */])(cell); + var parent = cell.parent; + var nextRow = parent.next; + var currentLineText = cm.getLine(line - 1); + var rowStr = createTableRow(parent); + + if (nextRow && nextRow.type === 'tableRow' || currentLineText !== rowStr) { + cm.setCursor(line - 1, Object(markdown["c" /* getMdEndCh */])(parent)); + cm.replaceSelection("\n" + rowStr); + cm.setCursor(line, 2); + } else { + cm.execCommand('deleteLine'); + } + } +}); +/* harmony default export */ var addLine = (AddLine); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/bold.js +/** + * @fileoverview Implements bold WysiwygCommand + * @author NHN FE Development Lab + */ + + +/** + * Bold + * Add bold to selected wysiwyg editor content + * @extends Command + * @module wysiwygCommands/Bold + * @ignore + */ + +var bold_Bold = commandManager["a" /* default */].command('wysiwyg', +/** @lends Bold */ +{ + name: 'Bold', + keyMap: ['CTRL+B', 'META+B'], + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var tableSelectionManager = wwe.componentManager.getManager('tableSelection'); + wwe.focus(); + + if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) { + tableSelectionManager.styleToSelectedCells(styleBold); + var range = sq.getSelection(); + range.collapse(true); + sq.setSelection(range); + } else { + styleBold(sq); + dom["a" /* default */].optimizeRange(sq.getSelection(), 'B'); + } + } +}); +/** + * Style bold. + * @param {object} sq - squire editor instance + */ + +function styleBold(sq) { + if (sq.hasFormat('b') || sq.hasFormat('strong')) { + sq.changeFormat(null, { + tag: 'b' + }); + } else if (!sq.hasFormat('PRE')) { + if (sq.hasFormat('code')) { + sq.changeFormat(null, { + tag: 'code' + }); + } + + sq.bold(); + } +} + +/* harmony default export */ var wysiwygCommands_bold = (bold_Bold); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/italic.js +/** + * @fileoverview Implements italic WysiwygCommand + * @author NHN FE Development Lab + */ + + +/** + * Italic + * Add Italic to selected wysiwyg editor content + * @extends Command + * @module wysiwygCommands/Italic + * @ignore + */ + +var italic_Italic = commandManager["a" /* default */].command('wysiwyg', +/** @lends Italic */ +{ + name: 'Italic', + keyMap: ['CTRL+I', 'META+I'], + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var tableSelectionManager = wwe.componentManager.getManager('tableSelection'); + wwe.focus(); + + if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) { + tableSelectionManager.styleToSelectedCells(styleItalic); + var range = sq.getSelection(); + range.collapse(true); + sq.setSelection(range); + } else { + styleItalic(sq); + dom["a" /* default */].optimizeRange(sq.getSelection(), 'I'); + } + } +}); +/** + * Style italic. + * @param {object} sq - squire editor instance + */ + +function styleItalic(sq) { + if (sq.hasFormat('i') || sq.hasFormat('em')) { + sq.changeFormat(null, { + tag: 'i' + }); + } else if (!sq.hasFormat('PRE')) { + if (sq.hasFormat('code')) { + sq.changeFormat(null, { + tag: 'code' + }); + } + + sq.italic(); + } +} + +/* harmony default export */ var wysiwygCommands_italic = (italic_Italic); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/strike.js +/** + * @fileoverview Implements strike WysiwygCommand + * @author NHN FE Development Lab + */ + + +/** + * Strike + * Add strike to selected wysiwyg editor content + * @extends Command + * @module wysiwygCommands/Strike + * @ignore + */ + +var strike_Strike = commandManager["a" /* default */].command('wysiwyg', +/** @lends Strike */ +{ + name: 'Strike', + keyMap: ['CTRL+S', 'META+S'], + + /** + * command handler + * @param {WysiwygEditor} wwe WysiwygEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var tableSelectionManager = wwe.componentManager.getManager('tableSelection'); + wwe.focus(); + + if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) { + tableSelectionManager.styleToSelectedCells(styleStrike); + var range = sq.getSelection(); + range.collapse(true); + sq.setSelection(range); + } else { + styleStrike(sq); + dom["a" /* default */].optimizeRange(sq.getSelection(), 'S'); + } + } +}); +/** + * Style strike. + * @param {object} sq - squire editor instance + */ + +function styleStrike(sq) { + if (sq.hasFormat('S')) { + sq.changeFormat(null, { + tag: 'S' + }); + } else if (!sq.hasFormat('PRE')) { + if (sq.hasFormat('code')) { + sq.changeFormat(null, { + tag: 'code' + }); + } + + sq.strikethrough(); + } +} + +/* harmony default export */ var wysiwygCommands_strike = (strike_Strike); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/blockquote.js +/** + * @fileoverview Implements block quote WysiwygCommand + * @author NHN FE Development Lab + */ + +/** + * Blockquote + * Add Blockquote to selected wysiwyg editor content + * @extends Command + * @module wysiwygCommands/Blockquote + * @ignore + */ + +var blockquote_Blockquote = commandManager["a" /* default */].command('wysiwyg', +/** @lends Blockquote */ +{ + name: 'Blockquote', + keyMap: ['ALT+Q', 'ALT+Q'], + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + wwe.focus(); + + if (!sq.hasFormat('TABLE') && !sq.hasFormat('PRE')) { + if (sq.hasFormat('BLOCKQUOTE')) { + sq.decreaseQuoteLevel(); + } else { + sq.increaseQuoteLevel(); + } + } + } +}); +/* harmony default export */ var wysiwygCommands_blockquote = (blockquote_Blockquote); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/addImage.js +/** + * @fileoverview Implements AddImage wysiwyg command + * @author NHN FE Development Lab + */ + + +var wysiwygCommands_addImage_decodeURIGraceful = importManager.decodeURIGraceful, + wysiwygCommands_addImage_encodeMarkdownCharacters = importManager.encodeMarkdownCharacters; +/** + * AddImage + * Add Image markdown syntax to wysiwyg Editor + * @extends Command + * @module wysiwygCommands/AddImage + * @ignore + */ + +var addImage_AddImage = commandManager["a" /* default */].command('wysiwyg', +/** @lends AddImage */ +{ + name: 'AddImage', + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + * @param {object} data data for image + */ + exec: function exec(wwe, data) { + var sq = wwe.getEditor(); + var altText = data.altText, + imageUrl = data.imageUrl; + altText = wysiwygCommands_addImage_decodeURIGraceful(altText); + imageUrl = wysiwygCommands_addImage_encodeMarkdownCharacters(imageUrl); + wwe.focus(); + + if (!sq.hasFormat('PRE')) { + sq.insertImage(imageUrl, { + alt: altText + }); + } + } +}); +/* harmony default export */ var wysiwygCommands_addImage = (addImage_AddImage); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/addLink.js +/** + * @fileoverview Implements AddLink wysiwyg command + * @author NHN FE Development Lab + */ + + + + +var wysiwygCommands_addLink_decodeURIGraceful = importManager.decodeURIGraceful, + addLink_encodeMarkdownCharacters = importManager.encodeMarkdownCharacters; +/** + * Add link markdown syntax to wysiwyg Editor + * @extends Command + * @module wysiwygCommands/AddLink + * @ignore + */ + +var addLink_AddLink = commandManager["a" /* default */].command('wysiwyg', +/** @lends AddLink */ +{ + name: 'AddLink', + + /** + * command handler + * @param {WysiwygEditor} wwe - wysiwygEditor instance + * @param {object} data - data for link + */ + exec: function exec(wwe, data) { + var sq = wwe.getEditor(); + var linkAttribute = wwe.getLinkAttribute(); + var url = data.url, + linkText = data.linkText; + var linkManager = wwe.componentManager.getManager('link'); + linkText = wysiwygCommands_addLink_decodeURIGraceful(linkText); + url = addLink_encodeMarkdownCharacters(url); + wwe.focus(); + + if (!sq.hasFormat('PRE')) { + sq.removeAllFormatting(); + var selectedText = sq.getSelectedText(); + + var selectedImageOnly = this._isSelectedImageOnly(sq.getSelection()); + + if (selectedText || selectedImageOnly) { + sq.makeLink(url, linkAttribute); + } else { + var link = sq.createElement('A', extend_default()({ + href: url + }, linkAttribute)); + link.textContent = linkText; + sq.insertElement(link); + } + + linkManager.addClassNameToImageLinksInSelection(); + } + }, + _isSelectedImageOnly: function _isSelectedImageOnly(range) { + if (!range.collapsed) { + var startContainer = range.startContainer, + endContainer = range.endContainer; + + if (startContainer && startContainer === endContainer) { + return dom["a" /* default */].isElemNode(startContainer) && startContainer.firstChild.nodeName === 'IMG'; + } + } + + return false; + } +}); +/* harmony default export */ var wysiwygCommands_addLink = (addLink_AddLink); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/hr.js +/** + * @fileoverview Implements HR wysiwyg command + * @author NHN FE Development Lab + */ + + +/** + * HR + * Add horizontal line markdown syntax to wysiwyg Editor + * @extends Command + * @module wysiwygCommands/HR + * @ignore + */ + +var hr_HR = commandManager["a" /* default */].command('wysiwyg', +/** @lends HR */ +{ + name: 'HR', + keyMap: ['CTRL+L', 'META+L'], + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var range = sq.getSelection(); + + if (range.collapsed && !sq.hasFormat('TABLE') && !sq.hasFormat('PRE')) { + var hr = document.createElement('hr'); + var currentNode = dom["a" /* default */].getChildNodeByOffset(range.startContainer, range.startOffset); + var nextBlockNode = dom["a" /* default */].getTopNextNodeUnder(currentNode, wwe.getBody()); // If nextBlockNode is div that has hr and has contenteditable as false, + // nextBlockNode should be set as nextSibling that is normal block. + + if (nextBlockNode && !dom["a" /* default */].isTextNode(nextBlockNode)) { + while (nextBlockNode && nextBlockNode.getAttribute('contenteditable') === 'false') { + nextBlockNode = nextBlockNode.nextSibling; + } + } + + if (!nextBlockNode) { + nextBlockNode = dom["a" /* default */].createEmptyLine(); + dom["a" /* default */].append(wwe.getBody(), nextBlockNode); + } + + sq.modifyBlocks(function (frag) { + frag.appendChild(hr); + return frag; + }); + var previousSibling = hr.previousSibling; + + if (previousSibling && dom["a" /* default */].isTextNode(previousSibling) && dom["a" /* default */].getTextLength(previousSibling) === 0) { + hr.parentNode.removeChild(previousSibling); + } + + hr.parentNode.replaceChild(dom["a" /* default */].createHorizontalRule(), hr); + range.selectNodeContents(nextBlockNode); + range.collapse(true); + sq.setSelection(range); + sq.saveUndoState(range); + } + + wwe.focus(); + } +}); +/* harmony default export */ var wysiwygCommands_hr = (hr_HR); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/heading.js +/** + * @fileoverview Implements Heading wysiwyg command + * @author NHN FE Development Lab + */ + + + +/** + * Heading + * Convert selected root level contents to heading with size wysiwyg Editor + * @extends Command + * @module wysiwygCommands/Heading + * @ignore + */ + +var heading_Heading = commandManager["a" /* default */].command('wysiwyg', +/** @lends Heading */ +{ + name: 'Heading', + + /** + * Command handler + * @param {WysiwygEditor} wwe WYSIWYGEditor instance + * @param {Number} size size + */ + exec: function exec(wwe, size) { + var sq = wwe.getEditor(); + var blockTagName = 'h1, h2, h3, h4, h5, h6, div'; + wwe.focus(); + + if (!sq.hasFormat('TABLE') && !sq.hasFormat('PRE')) { + sq.modifyBlocks(function (fragment) { + var blocks = dom["a" /* default */].children(fragment, blockTagName); + toArray_default()(blocks).forEach(function (block) { + var headingHTML = "h" + size; + + if (dom["a" /* default */].getNodeName(block) === 'DIV') { + dom["a" /* default */].wrap(block, headingHTML); + } else { + var wrapperHeading = document.createElement(headingHTML); + dom["a" /* default */].insertBefore(wrapperHeading, block); + wrapperHeading.innerHTML = block.innerHTML; + dom["a" /* default */].remove(block); + } + }); + return fragment; + }); + } + } +}); +/* harmony default export */ var wysiwygCommands_heading = (heading_Heading); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/paragraph.js +/** + * @fileoverview Implements Paragraph wysiwyg command + * @author NHN FE Development Lab + */ + + + +/** + * Paragraph + * Convert selected contents to paragraph only heading and list + * @extends Command + * @module wysiwygCommands/Paragraph + * @ignore + */ + +var paragraph_Paragraph = commandManager["a" /* default */].command('wysiwyg', +/** @lends Paragraph */ +{ + name: 'Paragraph', + + /** + * Command handler + * @param {WysiwygEditor} wwe WYSIWYGEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + wwe.focus(); + + if (!sq.hasFormat('TABLE') && !sq.hasFormat('PRE')) { + sq.modifyBlocks(function (fragment) { + var newFragment = document.createDocumentFragment(); + toArray_default()(fragment.childNodes).forEach(function (block) { + if (block.nodeName.match(/h\d/i)) { + appendChildrenTo(newFragment, block.children); + } else if (block.nodeName.match(/ul|ol/i)) { + dom["a" /* default */].findAll(block, 'li').forEach(function (listItem) { + appendChildrenTo(newFragment, listItem.children); + }); + } else { + newFragment.appendChild(block); + } + }); + return newFragment; + }); + } + } +}); +/** + * Append children + * @param {HTMLElement} parent - target to append + * @param {Array.} children - appending children + */ + +function appendChildrenTo(parent, children) { + toArray_default()(children).forEach(function (child) { + parent.appendChild(child.cloneNode(true)); + }); +} + +/* harmony default export */ var wysiwygCommands_paragraph = (paragraph_Paragraph); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/ul.js +/** + * @fileoverview Implements ul WysiwygCommand + * @author NHN FE Development Lab + */ + +/** + * UL + * Add UL to selected wysiwyg editor content + * @extends Command + * @module wysiwygCommands/UL + * @ignore + */ + +var ul_UL = commandManager["a" /* default */].command('wysiwyg', +/** @lends UL */ +{ + name: 'UL', + keyMap: ['CTRL+U', 'META+U'], + + /** + * Command Handler + * @param {WysiwygEditor} wwe WYSIWYGEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var range = sq.getSelection(); + var listManager = wwe.componentManager.getManager('list'); + var startContainer = range.startContainer, + endContainer = range.endContainer, + startOffset = range.startOffset, + endOffset = range.endOffset; + var newLIs = []; + wwe.focus(); + sq.saveUndoState(range); + + if (listManager.isAvailableMakeListInTable()) { + newLIs = listManager.createListInTable(range, 'UL'); + } else { + var lines = listManager.getLinesOfSelection(startContainer, endContainer); + + for (var i = 0; i < lines.length; i += 1) { + var newLI = this._changeFormatToUnorderedListIfNeed(wwe, lines[i]); + + if (newLI) { + newLIs.push(newLI); + } + } + } + + if (newLIs.length) { + listManager.adjustRange(startContainer, endContainer, startOffset, endOffset, newLIs); + } + }, + + /** + * Change format to unordered list if need + * @param {WysiwygEditor} wwe Wysiwyg editor instance + * @param {HTMLElement} target Element target for change + * @returns {HTMLElement} newly created list + * @private + */ + _changeFormatToUnorderedListIfNeed: function _changeFormatToUnorderedListIfNeed(wwe, target) { + var sq = wwe.getEditor(); + var range = sq.getSelection(); + var taskManager = wwe.componentManager.getManager('task'); + var newLI; + + if (!sq.hasFormat('PRE')) { + range.setStart(target, 0); + range.collapse(true); + sq.setSelection(range); + + if (sq.hasFormat('LI')) { + wwe.saveSelection(range); + taskManager.unformatTask(range.startContainer); + sq.replaceParent(range.startContainer, 'ol', 'ul'); + wwe.restoreSavedSelection(); + } else { + wwe.unwrapBlockTag(); + sq.makeUnorderedList(); + } + + newLI = sq.getSelection().startContainer; + } + + return newLI; + } +}); +/* harmony default export */ var wysiwygCommands_ul = (ul_UL); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/ol.js +/** + * @fileoverview Implements ol WysiwygCommand + * @author NHN FE Development Lab + */ + +/** + * OL + * Add OL to selected wysiwyg editor content + * @extends Command + * @module wysiwygCommands/OL + * @ignore + */ + +var ol_OL = commandManager["a" /* default */].command('wysiwyg', +/** @lends OL */ +{ + name: 'OL', + keyMap: ['CTRL+O', 'META+O'], + + /** + * Command Handler + * @param {WysiwygEditor} wwe WYSIWYGEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var range = sq.getSelection(); + var listManager = wwe.componentManager.getManager('list'); + var startContainer = range.startContainer, + startOffset = range.startOffset, + endContainer = range.endContainer, + endOffset = range.endOffset; + var newLIs = []; + wwe.focus(); + sq.saveUndoState(range); + + if (listManager.isAvailableMakeListInTable()) { + newLIs = listManager.createListInTable(range, 'OL'); + } else { + var lines = listManager.getLinesOfSelection(startContainer, endContainer); + + for (var i = 0; i < lines.length; i += 1) { + var newLI = this._changeFormatToOrderedListIfNeed(wwe, lines[i]); + + if (newLI) { + newLIs.push(newLI); + } + } + } + + if (newLIs.length) { + listManager.adjustRange(startContainer, endContainer, startOffset, endOffset, newLIs); + } + }, + + /** + * Change format to unordered list if need + * @param {WysiwygEditor} wwe Wysiwyg editor instance + * @param {HTMLElement} target Element target for change + * @returns {HTMLElement} newly created list item + * @private + */ + _changeFormatToOrderedListIfNeed: function _changeFormatToOrderedListIfNeed(wwe, target) { + var sq = wwe.getEditor(); + var range = sq.getSelection(); + var taskManager = wwe.componentManager.getManager('task'); + var newLI; + + if (!sq.hasFormat('PRE')) { + range.setStart(target, 0); + range.collapse(true); + sq.setSelection(range); + + if (sq.hasFormat('LI')) { + wwe.saveSelection(range); + taskManager.unformatTask(range.startContainer); + sq.replaceParent(range.startContainer, 'ul', 'ol'); + wwe.restoreSavedSelection(); + } else { + wwe.unwrapBlockTag(); + sq.makeOrderedList(); + } + + newLI = sq.getSelection().startContainer; + } + + return newLI; + } +}); +/* harmony default export */ var wysiwygCommands_ol = (ol_OL); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/table.js +/** + * @fileoverview Implements table WysiwygCommand + * @author NHN FE Development Lab + */ + +/** + * Table + * Add table to selected wysiwyg editor content + * @extends Command + * @module wysiwygCommands/Table + * @ignore + */ + +var table_Table = commandManager["a" /* default */].command('wysiwyg', +/** @lends Table */ +{ + name: 'Table', + + /** + * Command Handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + * @param {number} col column count + * @param {number} row row count + * @param {Array} data initial table data + */ + exec: function exec(wwe, col, row, data) { + var sq = wwe.getEditor(); + var tableIDClassName = wwe.componentManager.getManager('table').getTableIDClassName(); + var tableHTMLString; + + if (!sq.getSelection().collapsed || sq.hasFormat('TABLE') || sq.hasFormat('PRE')) { + wwe.focus(); + return; + } + + tableHTMLString = ""; + tableHTMLString += table_makeHeader(col, data); + tableHTMLString += table_makeBody(col, row - 1, data); + tableHTMLString += '
    '; + sq.insertHTML(tableHTMLString); + wwe.focus(); + + if (!data) { + focusToFirstTh(sq, wwe.getBody().querySelector("." + tableIDClassName)); + } + } +}); +/** + * Focus to first th + * @param {Squire} sq Squire instance + * @param {HTMLElement} table wrapped table element + */ + +function focusToFirstTh(sq, table) { + var range = sq.getSelection(); + range.selectNodeContents(table.querySelector('th')); + range.collapse(true); + sq.setSelection(range); +} +/** + * makeHeader + * make table header html string + * @param {number} col column count + * @param {string} data cell data + * @returns {string} html string + */ + + +function table_makeHeader(col, data) { + var header = ''; + var index = 0; + + while (col) { + header += ''; + + if (data) { + header += data[index]; + index += 1; + } + + header += ''; + col -= 1; + } + + header += ''; + return header; +} +/** + * makeBody + * make table body html string + * @param {number} col column count + * @param {number} row row count + * @param {string} data cell data + * @returns {string} html string + */ + + +function table_makeBody(col, row, data) { + var body = ''; + var index = col; + + for (var irow = 0; irow < row; irow += 1) { + body += ''; + + for (var icol = 0; icol < col; icol += 1) { + body += ''; + + if (data) { + body += data[index]; + index += 1; + } + + body += ''; + } + + body += ''; + } + + body += ''; + return body; +} + +/* harmony default export */ var wysiwygCommands_table = (table_Table); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/tableAddRow.js +/** + * @fileoverview Implements table add row WysiwygCommand + * @author NHN FE Development Lab + */ + + + + +/** + * AddRow + * Add Row to selected table + * @extends Command + * @module wysiwygCommands/TableAddRow + * @ignore + */ + +var TableAddRow = commandManager["a" /* default */].command('wysiwyg', +/** @lends AddRow */ +{ + name: 'AddRow', + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var range = sq.getSelection().cloneRange(); + var selectedRowLength = getSelectedRowsLength(wwe); + var tr, newRow; + wwe.focus(); + + if (sq.hasFormat('TD')) { + sq.saveUndoState(range); + tr = dom["a" /* default */].closest(range.startContainer, 'tr'); + + for (var i = 0; i < selectedRowLength; i += 1) { + newRow = getNewRow(tr); + dom["a" /* default */].insertAfter(newRow, tr); + } + + focusToFirstTd(sq, newRow); + } else if (sq.hasFormat('TH')) { + sq.saveUndoState(range); + tr = dom["a" /* default */].closest(range.startContainer, 'tr'); + + var _domUtils$parents = dom["a" /* default */].parents(tr, 'thead'), + thead = _domUtils$parents[0]; + + var tbody = thead.nextSibling; + + if (matches_default()(tbody, 'tbody')) { + var _domUtils$children = dom["a" /* default */].children(tbody, 'tr'); + + tr = _domUtils$children[0]; + } + + for (var _i = 0; _i < selectedRowLength; _i += 1) { + newRow = getNewRow(tr); + dom["a" /* default */].insertBefore(newRow, tr); + } + + focusToFirstTd(sq, newRow); + } + } +}); +/** + * get number of selected rows + * @param {WysiwygEditor} wwe - wysiwygEditor instance + * @returns {number} - number of selected rows + * @ignore + */ + +function getSelectedRowsLength(wwe) { + var selectionMgr = wwe.componentManager.getManager('tableSelection'); + var selectedCells = selectionMgr.getSelectedCells(); + var length = 1; + + if (selectedCells.length > 1) { + var first = selectedCells[0]; + var last = selectedCells[selectedCells.length - 1]; + var range = selectionMgr.getSelectionRangeFromTable(first, last); + length = range.to.row - range.from.row + 1; + } + + return length; +} +/** + * Get new row of given row + * @param {HTMLElement} tr - wrapped table row + * @returns {HTMLElement} - new cloned element + * @ignore + */ + + +function getNewRow(tr) { + var cloned = tr.cloneNode(true); + var htmlString = browser_default.a.msie ? '' : '
    '; + dom["a" /* default */].findAll(cloned, 'td').forEach(function (td) { + td.innerHTML = htmlString; + }); + return cloned; +} +/** + * Focus to first table cell + * @param {Squire} sq - Squire instance + * @param {HTMLElement} tr - wrapped table row + * @ignore + */ + + +function focusToFirstTd(sq, tr) { + var range = sq.getSelection(); + range.selectNodeContents(tr.querySelector('td')); + range.collapse(true); + sq.setSelection(range); +} + +/* harmony default export */ var tableAddRow = (TableAddRow); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/tableAddCol.js +/** + * @fileoverview Implements table add column WysiwygCommand + * @author NHN FE Development Lab + */ + + + + + +/** + * AddCol + * Add col to selected table + * @extends Command + * @module wysiwygCommands/TableAddCol + * @ignore + */ + +var TableAddCol = commandManager["a" /* default */].command('wysiwyg', +/** @lends AddCol */ +{ + name: 'AddCol', + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var range = sq.getSelection().cloneRange(); + var numberOfCols = getNumberOfCols(wwe); + var cell; + wwe.focus(); + + if (sq.hasFormat('TR')) { + sq.saveUndoState(range); + cell = getCellByRange(range); + addColToCellAfter(cell, numberOfCols); + focusToNextCell(sq, cell); + } + } +}); +/** + * get number of selected cols + * @param {WysiwygEditor} wwe - wysiwyg editor instance + * @returns {number} - number of selected cols + * @ignore + */ + +function getNumberOfCols(wwe) { + var selectionMgr = wwe.componentManager.getManager('tableSelection'); + var selectedCells = selectionMgr.getSelectedCells(); + var length = 1; + + if (selectedCells.length > 0) { + var maxLength = selectedCells[0].parentNode.querySelectorAll('td, th').length; + length = Math.min(maxLength, selectedCells.length); + } + + return length; +} +/** + * Get cell by range object + * @param {Range} range - range + * @returns {HTMLElement} - html element + * @ignore + */ + + +function getCellByRange(range) { + var cell = range.startContainer; + + if (dom["a" /* default */].getNodeName(cell) !== 'TD' && dom["a" /* default */].getNodeName(cell) !== 'TH') { + cell = dom["a" /* default */].closest(cell, 'td, th'); + } + + return cell; +} +/** + * Add column to after the current cell + * @param {HTMLElement} cell - wrapped table cell + * @param {number} [numberOfCols=1] - number of cols + * @ignore + */ + + +function addColToCellAfter(cell, numberOfCols) { + if (numberOfCols === void 0) { + numberOfCols = 1; + } + + var _domUtils$parents = dom["a" /* default */].parents(cell, 'table'), + table = _domUtils$parents[0]; + + if (table) { + var index = inArray_default()(cell, toArray_default()(cell.parentNode.childNodes)); + var cellToAdd; + dom["a" /* default */].findAll(table, 'tr').forEach(function (tr) { + var isTBody = dom["a" /* default */].getNodeName(tr.parentNode) === 'TBODY'; + var isMSIE = browser_default.a.msie; + var currentCell = tr.children[index]; + + for (var i = 0; i < numberOfCols; i += 1) { + if (isTBody) { + cellToAdd = document.createElement('td'); + } else { + cellToAdd = document.createElement('th'); + } + + if (!isMSIE) { + cellToAdd.appendChild(document.createElement('br')); + } + + dom["a" /* default */].insertAfter(cellToAdd, currentCell); + } + }); + } +} +/** + * Focus to next cell + * @param {Squire} sq - Squire instance + * @param {HTMLElement} cell - wrapped table cell + * @ignore + */ + + +function focusToNextCell(sq, cell) { + var range = sq.getSelection(); + range.selectNodeContents(cell.nextSibling); + range.collapse(true); + sq.setSelection(range); +} + +/* harmony default export */ var tableAddCol = (TableAddCol); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/tableRemoveRow.js +/** + * @fileoverview Implements table remove row WysiwygCommand + * @author NHN FE Development Lab + */ + + +/** + * RemoveRow + * remove Row to selected table + * @extends Command + * @module wysiwygCommands/TableRemoveRow + * @ignore + */ + +var TableRemoveRow = commandManager["a" /* default */].command('wysiwyg', +/** @lends RemoveRow */ +{ + name: 'RemoveRow', + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var range = sq.getSelection().cloneRange(); + + var _domUtils$parents = dom["a" /* default */].parents(range.startContainer, 'table'), + table = _domUtils$parents[0]; + + var selectionMgr = wwe.componentManager.getManager('tableSelection'); + var tableMgr = wwe.componentManager.getManager('table'); + var trs = getTrs(range, selectionMgr, table); + var tbodyRowLength = table.querySelectorAll('tbody tr').length; + wwe.focus(); + + if ((sq.hasFormat('TD') || sq.hasFormat('TABLE')) && tbodyRowLength > 1) { + sq.saveUndoState(range); + var firstTr = trs[0]; + var lastTr = trs[trs.length - 1]; + var nextFocus = lastTr && lastTr.nextSibling ? lastTr.nextSibling : firstTr && firstTr.previousSibling; + + if (nextFocus) { + tableRemoveRow_focusToFirstTd(sq, range, nextFocus, tableMgr); + } + + trs.forEach(function (tr) { + return dom["a" /* default */].remove(tr); + }); + } + + selectionMgr.removeClassAttrbuteFromAllCellsIfNeed(); + } +}); +/** + * Focus to first TD in given TR + * @param {SquireExt} sq Squire instance + * @param {Range} range Range object + * @param {HTMLElement} tr HTMLElement wrapped TR + * @param {object} tableMgr Table manager + */ + +function tableRemoveRow_focusToFirstTd(sq, range, tr, tableMgr) { + var nextFocusCell = tr.querySelector('td'); + range.setStart(nextFocusCell, 0); + range.collapse(true); + tableMgr.setLastCellNode(nextFocusCell); + sq.setSelection(range); +} +/** + * Get start, end row index from current range + * @param {HTMLElement} firstSelectedCell Range object + * @param {object} rangeInformation Range information object + * @param {HTMLElement} table HTMLElement wrapped TABLE + * @returns {HTMLElement} + */ + + +function getSelectedRows(firstSelectedCell, rangeInformation, table) { + var tbodyRowLength = table.querySelectorAll('tbody tr').length; + var isStartContainerInThead = dom["a" /* default */].parents(firstSelectedCell, 'thead').length; + var startRowIndex = rangeInformation.from.row; + var endRowIndex = rangeInformation.to.row; + + if (isStartContainerInThead) { + startRowIndex += 1; + } + + var isWholeTbodySelected = (startRowIndex === 1 || isStartContainerInThead) && endRowIndex === tbodyRowLength; + + if (isWholeTbodySelected) { + endRowIndex -= 1; + } + + return dom["a" /* default */].findAll(table, 'tr').slice(startRowIndex, endRowIndex + 1); +} +/** + * Get TRs + * @param {Range} range Range object + * @param {object} selectionMgr Table selection manager + * @param {HTMLElement} table current table + * @returns {Array.} + */ + + +function getTrs(range, selectionMgr, table) { + var selectedCells = selectionMgr.getSelectedCells(); + var rangeInformation, trs; + + if (selectedCells.length) { + rangeInformation = selectionMgr.getSelectionRangeFromTable(selectedCells[0], selectedCells[selectedCells.length - 1]); + trs = getSelectedRows(selectedCells[0], rangeInformation, table); + } else { + var cell = dom["a" /* default */].closest(range.startContainer, 'td,th'); + rangeInformation = selectionMgr.getSelectionRangeFromTable(cell, cell); + trs = getSelectedRows(cell, rangeInformation, table); + } + + return trs; +} + +/* harmony default export */ var tableRemoveRow = (TableRemoveRow); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/tableRemoveCol.js +/** + * @fileoverview Implements table remove column WysiwygCommand + * @author NHN FE Development Lab + */ + + + + +/** + * RemoveCol + * remove Row to selected table + * @extends Command + * @module wysiwygCommands/TableRemoveCol + * @ignore + */ + +var TableRemoveCol = commandManager["a" /* default */].command('wysiwyg', +/** @lends RemoveCol */ +{ + name: 'RemoveCol', + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var range = sq.getSelection().cloneRange(); + + var _domUtils$parents = dom["a" /* default */].parents(range.startContainer, 'table'), + table = _domUtils$parents[0]; + + var tableMgr = wwe.componentManager.getManager('table'); + var selectionMgr = wwe.componentManager.getManager('tableSelection'); + var hasMultipleCols = dom["a" /* default */].closest(range.startContainer, 'table').querySelectorAll('thead tr th').length > 1; + wwe.focus(); // IE 800a025e error on removing part of selection range. collapse + + range.collapse(true); + sq.setSelection(range); + + if (sq.hasFormat('TR', null, range) && hasMultipleCols) { + var trs = table.querySelectorAll('tbody tr'); + var tbodyColLength = trs.length ? trs[0].querySelectorAll('td').length : 0; + var selectedCells = selectionMgr.getSelectedCells(); + + if (selectedCells.length < tbodyColLength) { + sq.saveUndoState(range); + var nextFocus; + + if (selectedCells.length > 1) { + var tailCell = selectedCells[selectedCells.length - 1]; + var headCell = selectedCells[0]; + nextFocus = tailCell.nextSibling ? tailCell.nextSibling : headCell.previousSibling; + removeMultipleColsByCells(selectedCells); + } else { + var cell = tableRemoveCol_getCellByRange(range); + nextFocus = cell.nextSibling ? cell.nextSibling : cell.previousSibling; + removeColByCell(cell); + } + + focusToCell(sq, nextFocus, tableMgr); + } + } + } +}); +/** + * Get cell by range object + * @param {Range} range range + * @returns {HTMLElement|Node} + */ + +function tableRemoveCol_getCellByRange(range) { + var cell = range.startContainer; + + if (dom["a" /* default */].getNodeName(cell) !== 'TD' && !dom["a" /* default */].getNodeName(cell) === 'TH') { + cell = dom["a" /* default */].parentsUntil(cell, 'tr'); + } + + return cell; +} +/** + * Remove columns by given cells + * @param {HTMLElement} cells - table cells + */ + + +function removeMultipleColsByCells(cells) { + var numberOfCells = cells.length; + + for (var i = 0; i < numberOfCells; i += 1) { + var cellToDelete = cells[i]; + + if (cellToDelete) { + removeColByCell(cells[i]); + } + } +} +/** + * Remove column by given cell + * @param {HTMLElement} cell - wrapped table cell + */ + + +function removeColByCell(cell) { + var _domUtils$parents2 = dom["a" /* default */].parents(cell, 'table'), + table = _domUtils$parents2[0]; + + if (table) { + var index = inArray_default()(cell, toArray_default()(cell.parentNode.childNodes)); + dom["a" /* default */].findAll(table, 'tr').forEach(function (tr) { + var td = tr.children[index]; + dom["a" /* default */].remove(td); + }); + } +} +/** + * Focus to given cell + * @param {Squire} sq - Squire instance + * @param {HTMLElement} cell - wrapped table cell + * @param {object} tableMgr - Table manager instance + */ + + +function focusToCell(sq, cell, tableMgr) { + var nextFocusCell = cell; + + if (cell && dom["a" /* default */].isContain(document.body, cell)) { + var range = sq.getSelection(); + range.selectNodeContents(cell); + range.collapse(true); + sq.setSelection(range); + tableMgr.setLastCellNode(nextFocusCell); + } +} + +/* harmony default export */ var tableRemoveCol = (TableRemoveCol); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/tableAlignCol.js +/** + * @fileoverview Implements table align column WysiwygCommand + * @author NHN FE Development Lab + */ + + + +/** + * AlignCol + * Align selected column's text content to given direction + * @extends Command + * @module wysiwygCommands/TableAlignCol + * @ignore + */ + +var TableAlignCol = commandManager["a" /* default */].command('wysiwyg', +/** @lends AlignCol */ +{ + name: 'AlignCol', + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + * @param {string} alignDirection Align direction + */ + exec: function exec(wwe, alignDirection) { + var sq = wwe.getEditor(); + var range = sq.getSelection().cloneRange(); + var selectionMgr = wwe.componentManager.getManager('tableSelection'); + var rangeInformation = getRangeInformation(range, selectionMgr); + wwe.focus(); + + if (sq.hasFormat('TR')) { + sq.saveUndoState(range); + + var _domUtils$parents = dom["a" /* default */].parents(range.startContainer, 'table'), + table = _domUtils$parents[0]; + + var selectionInformation = getSelectionInformation(table, rangeInformation); + setAlignAttributeToTableCells(table, alignDirection, selectionInformation); + } + + selectionMgr.removeClassAttrbuteFromAllCellsIfNeed(); + } +}); +/** + * Set Column align + * @param {HTMLElement} table wrapped TABLE + * @param {string} alignDirection 'left' or 'center' or 'right' + * @param {{ + * startColumnIndex: number, + * endColumnIndex: number, + * isDivided: boolean + * }} selectionInformation start, end column index and boolean value for whether range divided or not + */ + +function setAlignAttributeToTableCells(table, alignDirection, selectionInformation) { + var isDivided = selectionInformation.isDivided || false; + var start = selectionInformation.startColumnIndex; + var end = selectionInformation.endColumnIndex; + var trs = dom["a" /* default */].findAll(table, 'tr'); + var columnLength = trs.length ? trs[0].querySelectorAll('td,th').length : 0; + trs.forEach(function (tr) { + var cells = toArray_default()(dom["a" /* default */].children(tr, 'td,th')); + cells.forEach(function (cell, index) { + if (isDivided && (start <= index && index <= columnLength || index <= end)) { + cell.setAttribute('align', alignDirection); + } else if (start <= index && index <= end) { + cell.setAttribute('align', alignDirection); + } + }); + }); +} +/** + * Return start, end column index and boolean value for whether range divided or not + * @param {HTMLElement} table wrapped TABLE + * @param {{startColumnIndex: number, endColumnIndex: number}} rangeInformation Range information + * @returns {{startColumnIndex: number, endColumnIndex: number, isDivided: boolean}} + */ + + +function getSelectionInformation(table, rangeInformation) { + var trs = table.querySelectorAll('tr'); + var columnLength = trs.length ? trs[0].querySelectorAll('td,th').length : 0; + var from = rangeInformation.from, + to = rangeInformation.to; + var startColumnIndex, endColumnIndex, isDivided; + + if (from.row === to.row) { + startColumnIndex = from.cell; + endColumnIndex = to.cell; + } else if (from.row < to.row) { + if (from.cell <= to.cell) { + startColumnIndex = 0; + endColumnIndex = columnLength - 1; + } else { + startColumnIndex = from.cell; + endColumnIndex = to.cell; + isDivided = true; + } + } + + return { + startColumnIndex: startColumnIndex, + endColumnIndex: endColumnIndex, + isDivided: isDivided + }; +} +/** + * Get range information + * @param {Range} range Range object + * @param {object} selectionMgr Table selection manager + * @returns {object} + */ + + +function getRangeInformation(range, selectionMgr) { + var selectedCells = selectionMgr.getSelectedCells(); + var rangeInformation, startCell; + + if (selectedCells.length) { + rangeInformation = selectionMgr.getSelectionRangeFromTable(selectedCells[0], selectedCells[selectedCells.length - 1]); + } else { + var startContainer = range.startContainer; + startCell = dom["a" /* default */].isTextNode(startContainer) ? dom["a" /* default */].parent(startContainer, 'td,th') : startContainer; + rangeInformation = selectionMgr.getSelectionRangeFromTable(startCell, startCell); + } + + return rangeInformation; +} + +/* harmony default export */ var tableAlignCol = (TableAlignCol); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/tableRemove.js +/** + * @fileoverview Implements table remove WysiwygCommand + * @author NHN FE Development Lab + */ + + +/** + * RemoveTable + * Remove selected table + * @extends Command + * @module wysiwygCommands/TableRemove + * @ignore + */ + +var TableRemove = commandManager["a" /* default */].command('wysiwyg', +/** @lends RemoveTable */ +{ + name: 'RemoveTable', + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var range = sq.getSelection().cloneRange(); + + if (sq.hasFormat('TABLE')) { + sq.saveUndoState(range); + dom["a" /* default */].remove(dom["a" /* default */].closest(range.startContainer, 'table')); + } + + wwe.focus(); + } +}); +/* harmony default export */ var tableRemove = (TableRemove); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/indent.js +/** + * @fileoverview Implements Indent wysiwyg command + * @author NHN FE Development Lab + */ + + + + +/** + * Indent + * Indent list or task to wysiwyg Editor + * @extends Command + * @module wysiwygCommands/indent + * @ignore + */ + +var indent_Indent = commandManager["a" /* default */].command('wysiwyg', +/** @lends Indent */ +{ + name: 'Indent', + + /** + * Command Handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + */ + exec: function exec(wwe) { + var listManager = wwe.componentManager.getManager('list'); + var range = wwe.getEditor().getSelection(); + var node = dom["a" /* default */].closest(range.startContainer, 'li'); + var prevClasses, nodeClasses, nextClasses; + var prev = node && node.previousSibling; + + if (prev) { + var next = node.querySelector('li'); + wwe.getEditor().saveUndoState(); + nodeClasses = node.className; + prevClasses = prev.className; + node.className = ''; + prev.className = ''; + + if (next) { + nextClasses = next.className; + var divElements = toArray_default()(next.children).filter(function (child) { + return matches_default()(child, 'div'); + }); + + if (!divElements.length) { + next.className = ''; + } + } + + wwe.getEditor().increaseListLevel(); + listManager.mergeList(node); + node.className = nodeClasses; + prev.className = prevClasses; + + if (next) { + next.className = nextClasses; + } + } + } +}); +/* harmony default export */ var wysiwygCommands_indent = (indent_Indent); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/outdent.js +/** + * @fileoverview Implements Outdent wysiwyg command + * @author NHN FE Development Lab + */ + + +/** + * Outdent + * Outdent list or task to wysiwyg Editor + * @extends Command + * @module wysiwygCommands/Outdent + * @ignore + */ + +var outdent_Outdent = commandManager["a" /* default */].command('wysiwyg', +/** @lends Outdent */ +{ + name: 'Outdent', + + /** + * Command Handler + * @param {WysiwygEditor} wwe WysiwygEditor instance + */ + exec: function exec(wwe) { + var node = getCurrentLi(wwe); + + if (node && isExecutable(node)) { + wwe.getEditor().saveUndoState(); + var nodeClasses = node.className; + wwe.getEditor().decreaseListLevel(); + node = getCurrentLi(wwe); + + if (node && nodeClasses) { + node.className = nodeClasses; + } + } + } +}); +/** + * test if outdent the given list item + * arbitrary list allows list item to be in any position + * while markdown spec does not + * @param {HTMLElement} currentLiNode - list item element + * @returns {boolean} - true to executable + * @ignore + */ + +function isExecutable(currentLiNode) { + var nodeName = dom["a" /* default */].getNodeName(currentLiNode.nextSibling); + return nodeName !== 'OL' && nodeName !== 'UL'; +} +/** + * Get list item element of current selection + * @param {object} wwe Wysiwyg editor instance + * @returns {HTMLElement} + * @ignore + */ + + +function getCurrentLi(wwe) { + var range = wwe.getEditor().getSelection(); + return dom["a" /* default */].closest(range.startContainer, 'li'); +} + +/* harmony default export */ var wysiwygCommands_outdent = (outdent_Outdent); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/task.js +/** + * @fileoverview Implements Task WysiwygCommand + * @author NHN FE Development Lab + */ + + +/** + * Task + * Add Task to selected wysiwyg editor content + * @extends Command + * @module wysiwygCommands/Task + * @ignore + */ + +var task_Task = commandManager["a" /* default */].command('wysiwyg', +/** @lends Task */ +{ + name: 'Task', + keyMap: ['ALT+T', 'ALT+T'], + + /** + * Command Handler + * @param {WysiwygEditor} wwe WYSIWYGEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var range = sq.getSelection(); + var listManager = wwe.componentManager.getManager('list'); + var startContainer = range.startContainer, + endContainer = range.endContainer, + startOffset = range.startOffset, + endOffset = range.endOffset; + var newLIs = []; + wwe.focus(); + sq.saveUndoState(range); + + if (listManager.isAvailableMakeListInTable()) { + newLIs = listManager.createListInTable(range, 'TASK'); + } else { + var lines = listManager.getLinesOfSelection(startContainer, endContainer); + + for (var i = 0; i < lines.length; i += 1) { + var newLI = this._changeFormatToTaskIfNeed(wwe, lines[i]); + + if (newLI) { + newLIs.push(newLI); + } + } + } + + if (newLIs.length) { + listManager.adjustRange(startContainer, endContainer, startOffset, endOffset, newLIs); + } + }, + + /** + * Change format to unordered list and return current li element if need + * @param {WysiwygEditor} wwe Wysiwyg editor instance + * @param {HTMLElement} target Element target for change + * @returns {HTMLElement} newly created list + * @private + */ + _changeFormatToTaskIfNeed: function _changeFormatToTaskIfNeed(wwe, target) { + var sq = wwe.getEditor(); + var range = sq.getSelection(); + var taskManager = wwe.componentManager.getManager('task'); + var newLI; + + if (!sq.hasFormat('PRE')) { + range.setStart(target, 0); + range.collapse(true); + sq.setSelection(range); + + if (!sq.hasFormat('li')) { + sq.makeUnorderedList(); + target = sq.getSelection().startContainer; + } + + if (hasClass_default()(target, 'task-list-item')) { + taskManager.unformatTask(target); + } else { + taskManager.formatTask(target); + } + + newLI = sq.getSelection().startContainer; + } + + return newLI; + } +}); +/* harmony default export */ var wysiwygCommands_task = (task_Task); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/code.js +/** + * @fileoverview Implements code WysiwygCommand + * @author NHN FE Development Lab + */ + + +/** + * Code + * Add bold to selected wysiwyg editor content + * @extends Command + * @module wysiwygCommands/Code + * @ignore + */ + +var code_Code = commandManager["a" /* default */].command('wysiwyg', +/** @lends Code */ +{ + name: 'Code', + keyMap: ['SHIFT+CTRL+C', 'SHIFT+META+C'], + + /** + * command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + */ + exec: function exec(wwe) { + var sq = wwe.getEditor(); + var tableSelectionManager = wwe.componentManager.getManager('tableSelection'); + + var _styleCode = styleCode.bind(null, wwe.getEditor()); + + wwe.focus(); + + if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) { + tableSelectionManager.styleToSelectedCells(_styleCode); + var range = sq.getSelection(); + range.collapse(true); + sq.setSelection(range); + } else { + _styleCode(sq); + } + } +}); +/** + * removeUnnecessaryCodeInNextToRange + * Remove unnecessary code tag next to range, code tag made by squire + * @param {Range} range range object + */ + +function removeUnnecessaryCodeInNextToRange(range) { + if (dom["a" /* default */].getNodeName(range.startContainer.nextSibling) === 'CODE' && dom["a" /* default */].getTextLength(range.startContainer.nextSibling) === 0) { + dom["a" /* default */].remove(range.startContainer.nextSibling); + } +} +/** + * Style code. + * @param {object} editor - editor instance + * @param {object} sq - squire editor instance + */ + + +function styleCode(editor, sq) { + if (!sq.hasFormat('PRE') && sq.hasFormat('code')) { + sq.changeFormat(null, { + tag: 'code' + }); + removeUnnecessaryCodeInNextToRange(editor.getSelection().cloneRange()); + } else if (!sq.hasFormat('a') && !sq.hasFormat('PRE')) { + if (sq.hasFormat('b')) { + sq.removeBold(); + } else if (sq.hasFormat('i')) { + sq.removeItalic(); + } + + sq.changeFormat({ + tag: 'code' + }); + var range = sq.getSelection().cloneRange(); + range.setStart(range.endContainer, range.endOffset); + range.collapse(true); + sq.setSelection(range); + } +} + +/* harmony default export */ var wysiwygCommands_code = (code_Code); +// CONCATENATED MODULE: ./src/js/wysiwygCommands/codeBlock.js +/** + * @fileoverview Implements code block WysiwygCommand + * @author NHN FE Development Lab + */ + + + +var CODEBLOCK_CLASS_TEMP = 'te-content-codeblock-temp'; +var codeBlock_CODEBLOCK_ATTR_NAME = 'data-te-codeblock'; +/** + * CodeBlock + * Add CodeBlock to wysiwygEditor + * @extends Command + * @module wysiwygCommands/Codeblock + * @ignore + */ + +var codeBlock_CodeBlock = commandManager["a" /* default */].command('wysiwyg', +/** @lends CodeBlock */ +{ + name: 'CodeBlock', + keyMap: ['SHIFT+CTRL+P', 'SHIFT+META+P'], + + /** + * Command handler + * @param {WysiwygEditor} wwe wysiwygEditor instance + * @param {string} type of language + */ + exec: function exec(wwe, type) { + var sq = wwe.getEditor(); + var range = sq.getSelection().cloneRange(); + + if (!sq.hasFormat('PRE') && !sq.hasFormat('TABLE')) { + var attr = codeBlock_CODEBLOCK_ATTR_NAME + " class = \"" + CODEBLOCK_CLASS_TEMP + "\""; + + if (type) { + attr += " data-language=\"" + type + "\""; + } + + var codeBlockBody = getCodeBlockBody(range, wwe); + sq.insertHTML("
    " + codeBlockBody + "
    "); + focusToFirstCode(wwe.getBody().querySelector("." + CODEBLOCK_CLASS_TEMP), wwe); + } + + wwe.focus(); + } +}); +/** + * focusToFirstCode + * Focus to first code tag content of pre tag + * @param {HTMLElement} pre pre tag + * @param {WysiwygEditor} wwe wysiwygEditor + */ + +function focusToFirstCode(pre, wwe) { + var range = wwe.getEditor().getSelection().cloneRange(); + removeClass_default()(pre, CODEBLOCK_CLASS_TEMP); + range.setStartBefore(pre.firstChild); + range.collapse(true); + wwe.getEditor().setSelection(range); +} +/** + * getCodeBlockBody + * get text wrapped by code + * @param {object} range range object + * @param {object} wwe wysiwyg editor + * @returns {string} + */ + + +function getCodeBlockBody(range, wwe) { + var mgr = wwe.componentManager.getManager('codeblock'); + var codeBlock; + + if (range.collapsed) { + codeBlock = '
    '; + } else { + var contents = range.extractContents(); + var nodes = toArray_default()(contents.childNodes); + var tempDiv = document.createElement('div'); + tempDiv.appendChild(mgr.prepareToPasteOnCodeblock(nodes)); + codeBlock = tempDiv.innerHTML; + } + + return codeBlock; +} + +/* harmony default export */ var wysiwygCommands_codeBlock = (codeBlock_CodeBlock); +// CONCATENATED MODULE: ./src/js/scroll/animation.js +var ANIMATION_TIME = 200; +var SCROLL_BOCKING_RESET_DELAY = 15; +var currentTimeoutId = null; +var releaseTimer = null; + +function run(deltaScrollTop, _ref) { + var syncScrollTop = _ref.syncScrollTop, + releaseEventBlock = _ref.releaseEventBlock; + clearTimeout(releaseTimer); + syncScrollTop(deltaScrollTop); + releaseTimer = setTimeout(function () { + releaseEventBlock(); + }, SCROLL_BOCKING_RESET_DELAY); +} + +function animate(sourceScrollTop, targetScrollTop, callbackObjForSync) { + var diff = targetScrollTop - sourceScrollTop; + var startTime = Date.now(); + /** + * Each animation step + */ + + var step = function step() { + var stepTime = Date.now(); + var progress = (stepTime - startTime) / ANIMATION_TIME; + var deltaValue; // if already doing animation + + if (currentTimeoutId) { + clearTimeout(currentTimeoutId); + } + + if (progress < 1) { + deltaValue = sourceScrollTop + diff * Math.cos((1 - progress) * Math.PI / 2); + run(Math.ceil(deltaValue), callbackObjForSync); + currentTimeoutId = setTimeout(step, 1); + } else { + run(targetScrollTop, callbackObjForSync); + currentTimeoutId = null; + } + }; + + step(); +} +// EXTERNAL MODULE: ./src/js/scroll/helper.js +var helper = __webpack_require__(18); + +// EXTERNAL MODULE: ./src/js/scroll/cache/offsetInfo.js +var offsetInfo = __webpack_require__(24); + +// CONCATENATED MODULE: ./src/js/scroll/editorScroll.js + + + + +var EDITING_POSITION_RATIO = 0.5; +var blockedPreviewScrollEvent = false; +var latestScrollTop = null; +/* eslint-disable no-return-assign */ + +function getAndSaveOffsetHeight(node, mdNodeId) { + var cachedHeight = Object(offsetInfo["a" /* getOffsetHeight */])(mdNodeId); + var offsetHeight = cachedHeight || node.offsetHeight; + + if (!cachedHeight) { + Object(offsetInfo["d" /* setOffsetHeight */])(mdNodeId, offsetHeight); + } + + return offsetHeight; +} + +function getTopInfo(cm, startLine, mdNode, node, previewEl) { + var mdNodeStartLine = Object(markdown["f" /* getMdStartLine */])(mdNode); + var height = cm.lineInfo(startLine).handle.height; + var previewElHeight = getAndSaveOffsetHeight(previewEl, 0); + var top = node.getBoundingClientRect().top - previewEl.getBoundingClientRect().top; // position editing node on middle of preview as default + + var additionalScrollTop = -previewElHeight * EDITING_POSITION_RATIO; + + if (Object(markdown["j" /* isMultiLineNode */])(mdNode)) { + var additionalTopPos = (startLine - mdNodeStartLine + 1) * height; + additionalScrollTop = additionalTopPos; + top += additionalTopPos; + } + + return { + top: top, + additionalScrollTop: additionalScrollTop + }; +} + +function syncPreviewScrollTopToMarkdown(editor, preview, scrollEvent) { + var root = preview._previewContent, + previewEl = preview.el; + var cm = editor.cm, + toastMark = editor.toastMark; + + var _cm$getScrollInfo = cm.getScrollInfo(), + left = _cm$getScrollInfo.left, + scrollTop = _cm$getScrollInfo.top, + height = _cm$getScrollInfo.height, + clientHeight = _cm$getScrollInfo.clientHeight; + + var isBottomPos = height - scrollTop <= clientHeight; + var sourceScrollTop = previewEl.scrollTop; + var targetScrollTop = isBottomPos ? previewEl.scrollHeight : 0; + + if (scrollTop && !isBottomPos) { + var _ref = scrollEvent ? cm.coordsChar({ + left: left, + top: scrollTop + }, 'local') : cm.getCursor('from'), + startLine = _ref.line; + + var firstMdNode = toastMark.findFirstNodeAtLine(startLine + 1); + + if (!firstMdNode || Object(markdown["g" /* isHtmlNode */])(firstMdNode)) { + return; + } // if DOM element does not exist, should get its parent node using markdown node + // in case of text node, rendererd DOM element is not matched to markdown node + + + var nodeObj = Object(helper["f" /* getParentNodeObj */])(firstMdNode); + var node = nodeObj.node, + mdNode = nodeObj.mdNode; + var mdNodeStartLine = Object(markdown["f" /* getMdStartLine */])(mdNode); + var previewElHeight = getAndSaveOffsetHeight(previewEl, 0); + targetScrollTop = Object(helper["g" /* getTotalOffsetTop */])(node, root) || node.offsetTop; + + if (!scrollEvent) { + var _getTopInfo = getTopInfo(cm, startLine, mdNode, node, previewEl), + top = _getTopInfo.top, + additionalScrollTop = _getTopInfo.additionalScrollTop; + + if (top > 0 && top < previewElHeight) { + return; + } + + targetScrollTop += additionalScrollTop; // assign the null to sync scrollTop position when scrolling + + latestScrollTop = null; + } else if (Object(helper["h" /* isNodeToBeCalculated */])(mdNode)) { + var offsetHeight = getAndSaveOffsetHeight(node, mdNode.id); + var offsetTop = cm.heightAtLine(mdNodeStartLine - 1, 'local'); + var cmNodeHeight = Object(helper["c" /* getCmRangeHeight */])(mdNode, cm); + targetScrollTop += Object(helper["b" /* getAdditionalTopPos */])(scrollTop, offsetTop, cmNodeHeight, offsetHeight); + var scrollTopInfo = { + latestScrollTop: latestScrollTop, + scrollTop: scrollTop, + targetScrollTop: targetScrollTop, + sourceScrollTop: sourceScrollTop + }; + targetScrollTop = Object(helper["d" /* getFallbackScrollTop */])(scrollTopInfo); + latestScrollTop = scrollTop; + + if (targetScrollTop === sourceScrollTop) { + return; + } + } + } + + blockedPreviewScrollEvent = true; + var callbackObjForSync = { + syncScrollTop: function syncScrollTop(deltaScrollTop) { + return previewEl.scrollTop = deltaScrollTop; + }, + releaseEventBlock: function releaseEventBlock() { + return blockedPreviewScrollEvent = false; + } + }; + animate(sourceScrollTop, targetScrollTop, callbackObjForSync); +} +function isBlockedPreviewScrollEvent() { + return blockedPreviewScrollEvent; +} +// CONCATENATED MODULE: ./src/js/scroll/previewScroll.js + + + + +var blockedMarkdownScrollEvent = false; +var previewScroll_latestScrollTop = null; +/* eslint-disable no-return-assign */ + +function getAndSaveOffsetInfo(node, mdNodeId, root) { + var cachedHeight = Object(offsetInfo["a" /* getOffsetHeight */])(mdNodeId); + var cachedTop = Object(offsetInfo["b" /* getOffsetTop */])(mdNodeId); + var offsetHeight = cachedHeight || node.offsetHeight; + var offsetTop = cachedTop || Object(helper["g" /* getTotalOffsetTop */])(node, root) || node.offsetTop; + + if (!cachedHeight) { + Object(offsetInfo["d" /* setOffsetHeight */])(mdNodeId, offsetHeight); + } + + if (!cachedTop) { + Object(offsetInfo["e" /* setOffsetTop */])(mdNodeId, offsetTop); + } + + return { + offsetHeight: offsetHeight, + offsetTop: offsetTop + }; +} + +function getAncestorHavingId(node, root) { + while (!node.getAttribute('data-nodeid') && node.parentElement !== root) { + node = node.parentElement; + } + + return node; +} + +function syncMarkdownScrollTopToPreview(editor, preview, targetNode) { + var toastMark = editor.toastMark, + cm = editor.cm; + var _preview$el = preview.el, + scrollTop = _preview$el.scrollTop, + clientHeight = _preview$el.clientHeight, + scrollHeight = _preview$el.scrollHeight; + var root = preview._previewContent; + var isBottomPos = scrollHeight - scrollTop <= clientHeight; + + var _cm$getScrollInfo = cm.getScrollInfo(), + left = _cm$getScrollInfo.left, + sourceScrollTop = _cm$getScrollInfo.top, + height = _cm$getScrollInfo.height; + + var targetScrollTop = isBottomPos ? height : 0; + + if (scrollTop && targetNode && !isBottomPos) { + targetNode = getAncestorHavingId(targetNode, root); + + if (!targetNode.getAttribute('data-nodeid')) { + return; + } + + var _cm$coordsChar = cm.coordsChar({ + left: left, + top: sourceScrollTop + }, 'local'), + startLine = _cm$coordsChar.line; + + var mdNodeId = Number(targetNode.getAttribute('data-nodeid')); + + var _getParentNodeObj = Object(helper["f" /* getParentNodeObj */])(toastMark.findNodeById(mdNodeId)), + mdNode = _getParentNodeObj.mdNode, + node = _getParentNodeObj.node; + + var mdNodeStartLine = Object(markdown["f" /* getMdStartLine */])(mdNode); + targetScrollTop = cm.heightAtLine(mdNodeStartLine - 1, 'local'); + + if (Object(markdown["i" /* isListItemNode */])(mdNode)) { + targetScrollTop += Object(helper["e" /* getNextEmptyLineHeight */])(cm, mdNodeStartLine, startLine); + } + + if (Object(helper["h" /* isNodeToBeCalculated */])(mdNode)) { + var cmNodeHeight = Object(helper["c" /* getCmRangeHeight */])(mdNode, cm); + + var _getAndSaveOffsetInfo = getAndSaveOffsetInfo(node, mdNodeId, root), + offsetHeight = _getAndSaveOffsetInfo.offsetHeight, + offsetTop = _getAndSaveOffsetInfo.offsetTop; + + targetScrollTop += Object(helper["b" /* getAdditionalTopPos */])(scrollTop, offsetTop, offsetHeight, cmNodeHeight); + var scrollTopInfo = { + latestScrollTop: previewScroll_latestScrollTop, + scrollTop: scrollTop, + targetScrollTop: targetScrollTop, + sourceScrollTop: sourceScrollTop + }; + targetScrollTop = Object(helper["d" /* getFallbackScrollTop */])(scrollTopInfo); + previewScroll_latestScrollTop = scrollTop; + + if (targetScrollTop === sourceScrollTop) { + return; + } + } + } + + blockedMarkdownScrollEvent = true; + var callbackObjForSync = { + syncScrollTop: function syncScrollTop(deltaScrollTop) { + return cm.scrollTo(0, deltaScrollTop); + }, + releaseEventBlock: function releaseEventBlock() { + return blockedMarkdownScrollEvent = false; + } + }; + animate(sourceScrollTop, targetScrollTop, callbackObjForSync); +} +function isBlockedMarkdownScrollEvent() { + return blockedMarkdownScrollEvent; +} +// CONCATENATED MODULE: ./src/js/scroll/ui/button.js + +var button_className = 'tui-scrollsync'; +var activeClassName = 'tui-scrollsync active'; +var active = true; +function isActive() { + return active; +} +function createButton(editor) { + if (editor.isViewer() || editor.getUI().name !== 'default') { + return; + } + + var i18n = editor.i18n; + var tooltip = { + ACTIVE: i18n.get('Auto scroll enabled'), + INACTIVE: i18n.get('Auto scroll disabled') + }; + var toolbar = editor.getUI().getToolbar(); + var buttonEl = document.createElement('button'); + buttonEl.className = activeClassName; + toolbar.addItem('divider'); + toolbar.addItem({ + type: 'button', + options: { + command: 'scrollSyncToggle', + tooltip: tooltip.ACTIVE, + el: buttonEl + } + }); + var items = toolbar.getItems(); + var divider = items[items.length - 2].el; + var button = items[items.length - 1]; + changeButtonVisiblityStateIfNeed(editor, button, divider); + addEventListener(editor, button, divider); + addEditorCommand(editor, button, tooltip); +} + +function addEventListener(editor, button, divider) { + // hide scroll follow button in wysiwyg + editor.on('changeMode', function () { + return changeButtonVisiblityStateIfNeed(editor, button, divider); + }); + editor.on('changePreviewStyle', function () { + return changeButtonVisiblityStateIfNeed(editor, button, divider); + }); +} + +function addEditorCommand(editor, button, tooltip) { + // Commands + editor.addCommand('markdown', { + name: 'scrollSyncToggle', + exec: function exec() { + active = !active; + + button._onOut(); + + if (active) { + button.el.className = activeClassName; + button.setTooltip(tooltip.ACTIVE); + } else { + button.el.className = button_className; + button.setTooltip(tooltip.INACTIVE); + } + + button._onOver(); + } + }); +} + +function changeButtonVisiblityStateIfNeed(editor, button, divider) { + if (editor.mdPreviewStyle === 'vertical' && editor.currentMode === 'markdown') { + css_default()(button.el, { + display: 'inline-block' + }); + css_default()(divider, { + display: 'inline-block' + }); + } else { + css_default()(button.el, { + display: 'none' + }); + css_default()(divider, { + display: 'none' + }); + } +} +// CONCATENATED MODULE: ./src/js/scroll/sync.js + + + +var isScrollable = true; +/* eslint-disable no-return-assign */ + +function register(editor) { + var mdEditor = editor.mdEditor, + preview = editor.preview; + createButton(editor); + addScrollEvent(mdEditor, preview); + addPreviewRenderedEvent(mdEditor, preview); + mdEditor.cm.on('change', function () { + return isScrollable = false; + }); +} + +function addPreviewRenderedEvent(editor, preview) { + editor.eventManager.listen('previewRenderAfter', function () { + // Immediately after the 'previewRenderAfter' event has occurred, + // browser rendering is not yet complete. + // So the size of elements can not be accurately measured. + setTimeout(function () { + if (isActive()) { + syncPreviewScrollTopToMarkdown(editor, preview); + } + + isScrollable = true; + }, 200); + }); +} + +function addScrollEvent(editor, preview) { + var eventManager = editor.eventManager; + eventManager.listen('scroll', function (_ref) { + var source = _ref.source, + data = _ref.data; + + if (!isActive()) { + return; + } + + if (isScrollable && preview.isVisible()) { + if (source === 'markdown' && !isBlockedMarkdownScrollEvent()) { + syncPreviewScrollTopToMarkdown(editor, preview, true); + } else if (source === 'preview' && !isBlockedPreviewScrollEvent()) { + syncMarkdownScrollTopToPreview(editor, preview, data); + } + } + }); +} +// CONCATENATED MODULE: ./src/js/editor.js +function editor_extends() { editor_extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return editor_extends.apply(this, arguments); } + +/** + * @fileoverview Implements Editor + * @author NHN FE Development Lab + */ + + + + + + + + + + + + + + + + + + + + + + + + + + + // markdown commands + + + + + + + + + + + + + + + + + + + + + + + // wysiwyg Commands + + + + + + + + + + + + + + + + + + + + + + + + + + +var __nedInstance = []; +/** + * @callback addImageBlobHook + * @param {File|Blob} fileOrBlob - image blob + * @param {callback} callback - callback function to be called after + * @param {string} source - source of an event the item belongs to. 'paste', 'drop', 'ui' + */ + +/** + * ToastUI Editor + * @param {Object} options Option object + * @param {HTMLElement} options.el - container element + * @param {string} [options.height='300px'] - Editor's height style value. Height is applied as border-box ex) '300px', '100%', 'auto' + * @param {string} [options.minHeight='200px'] - Editor's min-height style value in pixel ex) '300px' + * @param {string} [options.initialValue] - Editor's initial value + * @param {string} [options.previewStyle] - Markdown editor's preview style (tab, vertical) + * @param {boolean} [options.previewHighlight = true] - Highlight a preview element corresponds to the cursor position in the markdwon editor + * @param {string} [options.initialEditType] - Initial editor type (markdown, wysiwyg) + * @param {Object} [options.events] - Events + * @param {function} [options.events.load] - It would be emitted when editor fully load + * @param {function} [options.events.change] - It would be emitted when content changed + * @param {function} [options.events.stateChange] - It would be emitted when format change by cursor position + * @param {function} [options.events.focus] - It would be emitted when editor get focus + * @param {function} [options.events.blur] - It would be emitted when editor loose focus + * @param {Object} [options.hooks] - Hooks + * @param {function} [options.hooks.previewBeforeHook] - Submit preview to hook URL before preview be shown + * @param {addImageBlobHook} [options.hooks.addImageBlobHook] - hook for image upload + * @param {string} [options.language='en-US'] - language + * @param {boolean} [options.useCommandShortcut=true] - whether use keyboard shortcuts to perform commands + * @param {boolean} [options.useDefaultHTMLSanitizer=true] - use default htmlSanitizer + * @param {boolean} [options.usageStatistics=true] - send hostname to google analytics + * @param {Array.} [options.toolbarItems] - toolbar items. + * @param {boolean} [options.hideModeSwitch=false] - hide mode switch tab bar + * @param {Array.} [options.plugins] - Array of plugins. A plugin can be either a function or an array in the form of [function, options]. + * @param {Object} [options.extendedAutolinks] - Using extended Autolinks specified in GFM spec + * @param {Object} [options.customConvertor] - convertor extention + * @param {string} [options.placeholder] - The placeholder text of the editable element. + * @param {Object} [options.linkAttribute] - Attributes of anchor element that should be rel, target, contenteditable, hreflang, type + * @param {Object} [options.customHTMLRenderer] - Object containing custom renderer functions correspond to markdown node + * @param {boolean} [options.referenceDefinition=false] - whether use the specification of link reference definition + * @param {function} [options.customHTMLSanitizer=null] - custom HTML sanitizer + * @param {boolean} [options.frontMatter=false] - whether use the front matter + */ + +var editor_ToastUIEditor = /*#__PURE__*/function () { + function ToastUIEditor(options) { + var _this = this; + + this.initialHtml = options.el.innerHTML; + options.el.innerHTML = ''; + this.options = extend_default()({ + previewStyle: 'tab', + previewHighlight: true, + initialEditType: 'markdown', + height: '300px', + minHeight: '200px', + language: 'en-US', + useDefaultHTMLSanitizer: true, + useCommandShortcut: true, + usageStatistics: true, + toolbarItems: ['heading', 'bold', 'italic', 'strike', 'divider', 'hr', 'quote', 'divider', 'ul', 'ol', 'task', 'indent', 'outdent', 'divider', 'table', 'image', 'link', 'divider', 'code', 'codeblock'], + hideModeSwitch: false, + linkAttribute: null, + extendedAutolinks: false, + customConvertor: null, + customHTMLRenderer: null, + referenceDefinition: false, + customHTMLSanitizer: null, + frontMatter: false + }, options); + this.codeBlockLanguages = []; + this.eventManager = new js_eventManager["a" /* default */](); + this.importManager = new importManager(this.eventManager); + this.commandManager = new commandManager["a" /* default */](this, { + useCommandShortcut: this.options.useCommandShortcut + }); + var linkAttribute = Object(utils_common["c" /* sanitizeLinkAttribute */])(this.options.linkAttribute); + + var _getPluginInfo = Object(pluginHelper["a" /* getPluginInfo */])(this.options.plugins), + renderer = _getPluginInfo.renderer, + parser = _getPluginInfo.parser, + plugins = _getPluginInfo.plugins; + + var _this$options = this.options, + customHTMLRenderer = _this$options.customHTMLRenderer, + customHTMLSanitizer = _this$options.customHTMLSanitizer, + extendedAutolinks = _this$options.extendedAutolinks, + referenceDefinition = _this$options.referenceDefinition, + useDefaultHTMLSanitizer = _this$options.useDefaultHTMLSanitizer, + frontMatter = _this$options.frontMatter; + var rendererOptions = { + linkAttribute: linkAttribute, + customHTMLRenderer: editor_extends({}, renderer, customHTMLRenderer), + extendedAutolinks: extendedAutolinks, + referenceDefinition: referenceDefinition, + customParser: parser, + frontMatter: frontMatter, + customProp: { + showFrontMatter: frontMatter + } + }; + + if (this.options.customConvertor) { + // eslint-disable-next-line new-cap + this.convertor = new this.options.customConvertor(this.eventManager, rendererOptions); + } else { + this.convertor = new convertor["a" /* default */](this.eventManager, rendererOptions); + } + + var sanitizer = customHTMLSanitizer || (useDefaultHTMLSanitizer ? htmlSanitizer["a" /* default */] : null); + + if (sanitizer) { + this.convertor.initHtmlSanitizer(sanitizer); + } + + if (this.options.hooks) { + forEachOwnProperties_default()(this.options.hooks, function (fn, key) { + return _this.addHook(key, fn); + }); + } + + if (this.options.events) { + forEachOwnProperties_default()(this.options.events, function (fn, key) { + return _this.on(key, fn); + }); + } + + this.layout = new js_layout(options, this.eventManager); + this.i18n = i18n; + this.i18n.setCode(this.options.language); + this.setUI(this.options.UI || new defaultUI(this)); + this.toastMark = new toastmark["ToastMark"]('', { + disallowedHtmlBlockTags: ['br'], + extendedAutolinks: extendedAutolinks, + referenceDefinition: referenceDefinition, + disallowDeepHeading: true, + customParser: parser, + frontMatter: frontMatter + }); + this.mdEditor = markdownEditor.factory(this.layout.getMdEditorContainerEl(), this.eventManager, this.toastMark, this.options); + this.preview = new mdPreview["a" /* default */](this.layout.getPreviewEl(), this.eventManager, this.convertor, editor_extends({}, rendererOptions, { + isViewer: false, + highlight: this.options.previewHighlight + })); + this.wwEditor = wysiwygEditor.factory(this.layout.getWwEditorContainerEl(), this.eventManager, { + sanitizer: sanitizer, + linkAttribute: linkAttribute + }); + this.toMarkOptions = { + gfm: true, + renderer: toMarkRenderer + }; + + if (plugins) { + Object(pluginHelper["b" /* invokePlugins */])(plugins, this); + } + + this.changePreviewStyle(this.options.previewStyle); + this.changeMode(this.options.initialEditType, true); + this.minHeight(this.options.minHeight); + this.height(this.options.height); + this.setMarkdown(this.options.initialValue, false); + + if (this.options.placeholder) { + this.setPlaceholder(this.options.placeholder); + } + + if (!this.options.initialValue) { + this.setHtml(this.initialHtml, false); + } + + this.eventManager.emit('load', this); + + __nedInstance.push(this); + + this._addDefaultCommands(); + + if (this.options.usageStatistics) { + Object(utils_common["d" /* sendHostName */])(); + } + + register(this); + } + /** + * change preview style + * @param {string} style - 'tab'|'vertical' + */ + + + var _proto = ToastUIEditor.prototype; + + _proto.changePreviewStyle = function changePreviewStyle(style) { + this.layout.changePreviewStyle(style); + this.mdPreviewStyle = style; + this.eventManager.emit('changePreviewStyle', style); + this.eventManager.emit('previewNeedsRefresh', this.getMarkdown()); + } + /** + * call commandManager's exec method + * @param {*} ...args Command argument + */ + ; + + _proto.exec = function exec() { + var _this$commandManager; + + (_this$commandManager = this.commandManager).exec.apply(_this$commandManager, arguments); + } + /** + * add default commands + * @private + */ + ; + + _proto._addDefaultCommands = function _addDefaultCommands() { + this.addCommand(bold); + this.addCommand(italic); + this.addCommand(blockquote); + this.addCommand(markdownCommands_heading); + this.addCommand(paragraph); + this.addCommand(markdownCommands_hr); + this.addCommand(addLink); + this.addCommand(addImage); + this.addCommand(markdownCommands_ul); + this.addCommand(ol); + this.addCommand(markdownCommands_indent); + this.addCommand(outdent); + this.addCommand(markdownCommands_table); + this.addCommand(markdownCommands_task); + this.addCommand(markdownCommands_code); + this.addCommand(markdownCommands_codeBlock); + this.addCommand(strike); + this.addCommand(changeTaskMarker); + this.addCommand(toggleTaskMarker); + this.addCommand(moveNextCursorOrIndent); + this.addCommand(movePrevCursorOrOutdent); + this.addCommand(addLine); + this.addCommand(wysiwygCommands_bold); + this.addCommand(wysiwygCommands_italic); + this.addCommand(wysiwygCommands_blockquote); + this.addCommand(wysiwygCommands_ul); + this.addCommand(wysiwygCommands_ol); + this.addCommand(wysiwygCommands_addImage); + this.addCommand(wysiwygCommands_addLink); + this.addCommand(wysiwygCommands_hr); + this.addCommand(wysiwygCommands_heading); + this.addCommand(wysiwygCommands_paragraph); + this.addCommand(wysiwygCommands_indent); + this.addCommand(wysiwygCommands_outdent); + this.addCommand(wysiwygCommands_task); + this.addCommand(wysiwygCommands_table); + this.addCommand(tableAddRow); + this.addCommand(tableAddCol); + this.addCommand(tableRemoveRow); + this.addCommand(tableRemoveCol); + this.addCommand(tableAlignCol); + this.addCommand(tableRemove); + this.addCommand(wysiwygCommands_code); + this.addCommand(wysiwygCommands_codeBlock); + this.addCommand(wysiwygCommands_strike); + }; + + _proto.addCommand = function addCommand(type, props) { + if (!props) { + this.commandManager.addCommand(type); + } else { + this.commandManager.addCommand(commandManager["a" /* default */].command(type, props)); + } + } + /** + * After added command. + */ + ; + + _proto.afterAddedCommand = function afterAddedCommand() { + this.eventManager.emit('afterAddedCommand', this); + } + /** + * Bind eventHandler to event type + * @param {string} type Event type + * @param {function} handler Event handler + */ + ; + + _proto.on = function on(type, handler) { + this.eventManager.listen(type, handler); + } + /** + * Unbind eventHandler from event type + * @param {string} type Event type + */ + ; + + _proto.off = function off(type) { + this.eventManager.removeEventHandler(type); + } + /** + * Add hook to TUIEditor event + * @param {string} type Event type + * @param {function} handler Event handler + */ + ; + + _proto.addHook = function addHook(type, handler) { + this.eventManager.removeEventHandler(type); + this.eventManager.listen(type, handler); + } + /** + * Remove hook from TUIEditor event + * @param {string} type Event type + */ + ; + + _proto.removeHook = function removeHook(type) { + this.eventManager.removeEventHandler(type); + } + /** + * Get CodeMirror instance + * @returns {CodeMirror} + */ + ; + + _proto.getCodeMirror = function getCodeMirror() { + return this.mdEditor.getEditor(); + } + /** + * Get SquireExt instance + * @returns {SquireExt} + */ + ; + + _proto.getSquire = function getSquire() { + return this.wwEditor.getEditor(); + } + /** + * Set focus to current Editor + */ + ; + + _proto.focus = function focus() { + this.getCurrentModeEditor().focus(); + } + /** + * Remove focus of current Editor + */ + ; + + _proto.blur = function blur() { + this.getCurrentModeEditor().blur(); + } + /** + * Set cursor position to end + */ + ; + + _proto.moveCursorToEnd = function moveCursorToEnd() { + this.getCurrentModeEditor().moveCursorToEnd(); + } + /** + * Set cursor position to start + */ + ; + + _proto.moveCursorToStart = function moveCursorToStart() { + this.getCurrentModeEditor().moveCursorToStart(); + } + /** + * Set markdown syntax text. + * @param {string} markdown - markdown syntax text. + * @param {boolean} [cursorToEnd=true] - move cursor to contents end + */ + ; + + _proto.setMarkdown = function setMarkdown(markdown, cursorToEnd) { + if (cursorToEnd === void 0) { + cursorToEnd = true; + } + + markdown = markdown || ''; + + if (this.isMarkdownMode()) { + this.mdEditor.setValue(markdown, cursorToEnd); + } else { + this.wwEditor.setValue(this.convertor.toHTML(markdown), cursorToEnd); + } + + this.eventManager.emit('setMarkdownAfter', markdown); + } + /** + * Set html value. + * @param {string} html - html syntax text + * @param {boolean} [cursorToEnd=true] - move cursor to contents end + */ + ; + + _proto.setHtml = function setHtml(html, cursorToEnd) { + if (cursorToEnd === void 0) { + cursorToEnd = true; + } + + html = html || ''; + this.wwEditor.setValue(html, cursorToEnd); + + if (this.isMarkdownMode()) { + var markdown = this.convertor.toMarkdown(this.wwEditor.getValue(), this.toMarkOptions); + this.mdEditor.setValue(markdown, cursorToEnd); + this.eventManager.emit('setMarkdownAfter', markdown); + } + } + /** + * Get markdown syntax text. + * @returns {string} + */ + ; + + _proto.getMarkdown = function getMarkdown() { + var markdown; + + if (this.isMarkdownMode()) { + markdown = this.mdEditor.getValue(); + } else { + markdown = this.convertor.toMarkdown(this.wwEditor.getValue(), this.toMarkOptions); + } + + return markdown; + } + /** + * Get html syntax text. + * @returns {string} + */ + ; + + _proto.getHtml = function getHtml() { + if (this.isWysiwygMode()) { + this.mdEditor.setValue(this.convertor.toMarkdown(this.wwEditor.getValue(), this.toMarkOptions)); + } + + return this.convertor.toHTML(this.mdEditor.getValue()); + } + /** + * Insert text + * @param {string} text - text string to insert + */ + ; + + _proto.insertText = function insertText(text) { + if (this.isMarkdownMode()) { + this.mdEditor.replaceSelection(text); + } else { + this.wwEditor.insertText(text); + } + } + /** + * Add widget to selection + * @param {Range} selection Current selection + * @param {Node} node widget node + * @param {string} style Adding style "over" or "bottom" + * @param {number} [offset] Offset for adjust position + */ + ; + + _proto.addWidget = function addWidget(selection, node, style, offset) { + this.getCurrentModeEditor().addWidget(selection, node, style, offset); + } + /** + * Set and return edithr height + * @param {string} height - editor height + * @returns {string} editor height + */ + ; + + _proto.height = function height(_height) { + if (isExisty_default()(_height)) { + var el = this.options.el; + + if (_height === 'auto') { + addClass_default()(el, 'auto-height'); + this.minHeight(this.minHeight()); + } else { + removeClass_default()(el, 'auto-height'); + this.minHeight(_height); + } + + if (isNumber_default()(_height)) { + _height = _height + "px"; + } + + css_default()(this.options.el, { + height: _height + }); + this._height = _height; + } + + return this._height; + } + /** + * Set / Get min content height + * @param {string} minHeight - min content height in pixel + * @returns {string} - min height in pixel + */ + ; + + _proto.minHeight = function minHeight(_minHeight) { + if (isExisty_default()(_minHeight)) { + var editorHeight = this._ui.getEditorHeight(); + + var editorSectionHeight = this._ui.getEditorSectionHeight(); + + var diffHeight = editorHeight - editorSectionHeight; + this._minHeight = _minHeight; + _minHeight = parseInt(_minHeight, 10); + _minHeight = Math.max(_minHeight - diffHeight, 0); + this.wwEditor.setMinHeight(_minHeight); + this.mdEditor.setMinHeight(_minHeight); + this.preview.setMinHeight(_minHeight); + } + + return this._minHeight; + } + /** + * Get current editor mode name + * @returns {Object} MarkdownEditor or WysiwygEditor + */ + ; + + _proto.getCurrentModeEditor = function getCurrentModeEditor() { + var editor; + + if (this.isMarkdownMode()) { + editor = this.mdEditor; + } else { + editor = this.wwEditor; + } + + return editor; + } + /** + * Return true if current editor mode is Markdown + * @returns {boolean} + */ + ; + + _proto.isMarkdownMode = function isMarkdownMode() { + return this.currentMode === 'markdown'; + } + /** + * Return true if current editor mode is WYSIWYG + * @returns {boolean} + */ + ; + + _proto.isWysiwygMode = function isWysiwygMode() { + return this.currentMode === 'wysiwyg'; + } + /** + * Return false + * @returns {boolean} + */ + ; + + _proto.isViewer = function isViewer() { + return false; + } + /** + * Get current Markdown editor's preview style + * @returns {string} + */ + ; + + _proto.getCurrentPreviewStyle = function getCurrentPreviewStyle() { + return this.mdPreviewStyle; + } + /** + * Change editor's mode to given mode string + * @param {string} mode - Editor mode name of want to change + * @param {boolean} [isWithoutFocus] - Change mode without focus + */ + ; + + _proto.changeMode = function changeMode(mode, isWithoutFocus) { + if (this.currentMode === mode) { + return; + } + + this.eventManager.emit('changeModeBefore', this.currentMode); + this.currentMode = mode; + + if (this.isWysiwygMode()) { + this.layout.switchToWYSIWYG(); + this.wwEditor.setValue(this.convertor.toHTML(this.mdEditor.getValue()), !isWithoutFocus); + this.eventManager.emit('changeModeToWysiwyg'); + } else { + this.layout.switchToMarkdown(); + this.mdEditor.resetState(); + this.mdEditor.setValue(this.convertor.toMarkdown(this.wwEditor.getValue(), this.toMarkOptions), !isWithoutFocus); + this.getCodeMirror().refresh(); + this.eventManager.emit('changeModeToMarkdown'); + } + + this.eventManager.emit('changeMode', mode); + + if (!isWithoutFocus) { + this.focus(); + } + } + /** + * Remove TUIEditor from document + */ + ; + + _proto.remove = function remove() { + var self = this; + var i = __nedInstance.length - 1; + this.wwEditor.remove(); + this.mdEditor.remove(); + this.layout.remove(); + this.preview.remove(); + + if (this.getUI()) { + this.getUI().remove(); + } + + this.eventManager.emit('removeEditor'); + this.eventManager.events.forEach(function (value, key) { + self.off(key); + }); + this.eventManager = null; + + for (; i >= 0; i -= 1) { + if (__nedInstance[i] === this) { + __nedInstance.splice(i, 1); + } + } + } + /** + * Hide TUIEditor + */ + ; + + _proto.hide = function hide() { + this.eventManager.emit('hide', this); + } + /** + * Show TUIEditor + */ + ; + + _proto.show = function show() { + this.eventManager.emit('show', this); + this.getCodeMirror().refresh(); + } + /** + * Scroll Editor content to Top + * @param {number} value Scroll amount + * @returns {number} + */ + ; + + _proto.scrollTop = function scrollTop(value) { + return this.getCurrentModeEditor().scrollTop(value); + } + /** + * Set UI to private UI property + * @param {UI} UI UI instance + */ + ; + + _proto.setUI = function setUI(UI) { + this._ui = UI; + } + /** + * Get _ui property + * @returns {DefaultUI|UI} + */ + ; + + _proto.getUI = function getUI() { + return this._ui; + } + /** + * Reset TUIEditor + */ + ; + + _proto.reset = function reset() { + this.wwEditor.reset(); + this.mdEditor.reset(); + } + /** + * Get current range + * @returns {{start, end}|Range} + */ + ; + + _proto.getRange = function getRange() { + return this.getCurrentModeEditor().getRange(); + } + /** + * Get text object of current range + * @param {{start, end}|Range} range Range object of each editor + * @returns {MdTextObject|WwTextObject} TextObject class + */ + ; + + _proto.getTextObject = function getTextObject(range) { + return this.getCurrentModeEditor().getTextObject(range); + } + /** + * get selected text + * @returns {string} - selected text + */ + ; + + _proto.getSelectedText = function getSelectedText() { + var range = this.getRange(); + var textObject = this.getTextObject(range); + return textObject.getTextContent() || ''; + } + /** + * Set the placeholder on all editors + * @param {string} placeholder - placeholder to set + */ + ; + + _proto.setPlaceholder = function setPlaceholder(placeholder) { + this.mdEditor.setPlaceholder(placeholder); + this.wwEditor.setPlaceholder(placeholder); + } + /** + * Set code block languages + * @param {Array} languages - code language list + */ + ; + + _proto.setCodeBlockLanguages = function setCodeBlockLanguages(languages) { + var _this2 = this; + + if (languages === void 0) { + languages = []; + } + + languages.forEach(function (lang) { + if (_this2.codeBlockLanguages.indexOf(lang) < 0) { + _this2.codeBlockLanguages.push(lang); + } + }); + this.eventManager.emit('setCodeBlockLanguages', this.codeBlockLanguages); + } + /** + * Get instance of TUIEditor + * @returns {Array} + */ + ; + + ToastUIEditor.getInstances = function getInstances() { + return __nedInstance; + } + /** + * Factory method for Editor + * @param {object} options Option for initialize TUIEditor + * @returns {object} ToastUIEditor or ToastUIEditorViewer + */ + ; + + ToastUIEditor.factory = function factory(options) { + var tuiEditor; + + if (options.viewer) { + tuiEditor = new viewer["a" /* default */](options); + } else { + tuiEditor = new ToastUIEditor(options); + } + + return tuiEditor; + } + /** + * Set language + * @param {string} code - code for I18N language + * @param {object} data - language set + */ + ; + + ToastUIEditor.setLanguage = function setLanguage(code, data) { + i18n.setLanguage(code, data); + }; + + return ToastUIEditor; +}(); // (Not an official API) +// Create a function converting markdown to HTML using the internal parser and renderer. + + +editor_ToastUIEditor._createMarkdownToHTML = createMarkdownToHTML; +/** + * Check whether is viewer (using in plugins) + * @type {boolean} + */ + +editor_ToastUIEditor.isViewer = false; +/** + * CodeBlockManager instance using in plugins + * @type {CodeBlockManager} + * @ignore + */ + +editor_ToastUIEditor.codeBlockManager = codeBlockManager["a" /* default */]; +/** + * WwCodeBlockManager class using in plugins + * @type {Class.} + * @ignore + */ + +editor_ToastUIEditor.WwCodeBlockManager = wwCodeBlockManager; +/** + * WwTableManager class using in plugins + * @type {Class.} + * @ignore + */ + +editor_ToastUIEditor.WwTableManager = wwTableManager; +/** + * WwTableManager class using in plugins + * @type {Class.} + * @ignore + */ + +editor_ToastUIEditor.WwTableSelectionManager = wwTableSelectionManager; +/** + * CommandManager class using in plugins + * @type {Class.} + * @ignore + */ + +editor_ToastUIEditor.CommandManager = commandManager["a" /* default */]; +/* harmony default export */ var js_editor = (editor_ToastUIEditor); +// EXTERNAL MODULE: ./src/css/editor.css +var css_editor = __webpack_require__(50); + +// EXTERNAL MODULE: ./src/css/contents.css +var css_contents = __webpack_require__(51); + +// EXTERNAL MODULE: ./src/css/preview-highlighting.css +var preview_highlighting = __webpack_require__(41); + +// EXTERNAL MODULE: ./src/css/md-syntax-highlighting.css +var md_syntax_highlighting = __webpack_require__(52); + +// CONCATENATED MODULE: ./src/js/i18n/en-us.js +/** + * @fileoverview I18N for English + * @author NHN FE Development Lab + */ + +js_editor.setLanguage(['en', 'en-US'], { + Markdown: 'Markdown', + WYSIWYG: 'WYSIWYG', + Write: 'Write', + Preview: 'Preview', + Headings: 'Headings', + Paragraph: 'Paragraph', + Bold: 'Bold', + Italic: 'Italic', + Strike: 'Strike', + Code: 'Inline code', + Line: 'Line', + Blockquote: 'Blockquote', + 'Unordered list': 'Unordered list', + 'Ordered list': 'Ordered list', + Task: 'Task', + Indent: 'Indent', + Outdent: 'Outdent', + 'Insert link': 'Insert link', + 'Insert CodeBlock': 'Insert codeBlock', + 'Insert table': 'Insert table', + 'Insert image': 'Insert image', + Heading: 'Heading', + 'Image URL': 'Image URL', + 'Select image file': 'Select image file', + Description: 'Description', + OK: 'OK', + More: 'More', + Cancel: 'Cancel', + File: 'File', + URL: 'URL', + 'Link text': 'Link text', + 'Add row': 'Add row', + 'Add col': 'Add col', + 'Remove row': 'Remove row', + 'Remove col': 'Remove col', + 'Align left': 'Align left', + 'Align center': 'Align center', + 'Align right': 'Align right', + 'Remove table': 'Remove table', + 'Would you like to paste as table?': 'Would you like to paste as table?', + 'Text color': 'Text color', + 'Auto scroll enabled': 'Auto scroll enabled', + 'Auto scroll disabled': 'Auto scroll disabled', + 'Choose language': 'Choose language' +}); +// CONCATENATED MODULE: ./src/js/index.js +/** + * @fileoverview entry point for editor + * @author NHN FE Development Lab + */ + + + + + + +/* harmony default export */ var js = __webpack_exports__["default"] = (js_editor); + +/***/ }) +/******/ ])["default"]; +}); \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/tui-editor-2x.png b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/tui-editor-2x.png deleted file mode 100644 index 557607b4cb..0000000000 Binary files a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/tui-editor-2x.png and /dev/null differ diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/tui-editor-Editor-all.js b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/tui-editor-Editor-all.js deleted file mode 100644 index ff66874a58..0000000000 --- a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/tui-editor/tui-editor-Editor-all.js +++ /dev/null @@ -1,42211 +0,0 @@ -/*! - * tui-editor - * @version 1.4.10 - * @author NHN FE Development Lab (https://nhn.github.io/tui.editor/) - * @license MIT - */ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require("jquery"), require("tui-code-snippet"), require("codemirror"), require("to-mark"), require("tui-chart"), require("squire-rte"), require("markdown-it"), require("highlight.js"), require("tui-color-picker"), require("plantuml-encoder")); - else if(typeof define === 'function' && define.amd) - define(["jquery", "tui-code-snippet", "codemirror", "to-mark", "tui-chart", "squire-rte", "markdown-it", "highlight.js", "tui-color-picker", "plantuml-encoder"], factory); - else if(typeof exports === 'object') - exports["Editor"] = factory(require("jquery"), require("tui-code-snippet"), require("codemirror"), require("to-mark"), require("tui-chart"), require("squire-rte"), require("markdown-it"), require("highlight.js"), require("tui-color-picker"), require("plantuml-encoder")); - else - root["tui"] = root["tui"] || {}, root["tui"]["Editor"] = factory(root["$"], root["tui"]["util"], root["CodeMirror"], root["toMark"], root["tui"]["chart"], root["Squire"], root["markdownit"], root["hljs"], root["tui"]["colorPicker"], root["plantumlEncoder"]); -})(window, function(__WEBPACK_EXTERNAL_MODULE__0__, __WEBPACK_EXTERNAL_MODULE__1__, __WEBPACK_EXTERNAL_MODULE__10__, __WEBPACK_EXTERNAL_MODULE__24__, __WEBPACK_EXTERNAL_MODULE__57__, __WEBPACK_EXTERNAL_MODULE__79__, __WEBPACK_EXTERNAL_MODULE__85__, __WEBPACK_EXTERNAL_MODULE__94__, __WEBPACK_EXTERNAL_MODULE__207__, __WEBPACK_EXTERNAL_MODULE__209__) { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function(value, mode) { -/******/ if(mode & 1) value = __webpack_require__(value); -/******/ if(mode & 8) return value; -/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = "/dist"; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 55); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE__0__; - -/***/ }), -/* 1 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE__1__; - -/***/ }), -/* 2 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview Implements CommandManager - * @author NHN FE Development Lab - */ - - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _command = __webpack_require__(84); - -var _command2 = _interopRequireDefault(_command); - -var _util = __webpack_require__(39); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var KEYMAP_OS_INDEX = _util.isMac ? 1 : 0; - -/** - * Class CommandManager - * @param {ToastUIEditor} base nedInstance - * @param {object} [options={}] - option object - * @param {boolean} [options.useCommandShortcut=true] - execute command with keyMap - * @ignore - */ - -var CommandManager = function () { - function CommandManager(base) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - _classCallCheck(this, CommandManager); - - this._command = new _tuiCodeSnippet2.default.Map(); - this._mdCommand = new _tuiCodeSnippet2.default.Map(); - this._wwCommand = new _tuiCodeSnippet2.default.Map(); - this._options = _jquery2.default.extend({ - 'useCommandShortcut': true - }, options); - - this.base = base; - - this.keyMapCommand = {}; - - this._initEvent(); - } - - /** - * You can change command before command addition by addCommandBefore event. - * @param {object} command - command - * @returns {object} - * @private - */ - - - _createClass(CommandManager, [{ - key: '_addCommandBefore', - value: function _addCommandBefore(command) { - var commandWrapper = { command: command }; - - this.base.eventManager.emit('addCommandBefore', commandWrapper); - - return commandWrapper.command || command; - } - - /** - * Add command - * @param {Command} command Command instance - * @returns {Command} Command - */ - - }, { - key: 'addCommand', - value: function addCommand(command) { - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - if (args.length) { - command = CommandManager.command.apply(CommandManager, [command].concat(args)); - } - - command = this._addCommandBefore(command); - - var name = command.getName(); - - var commandBase = void 0; - - if (command.isMDType()) { - commandBase = this._mdCommand; - } else if (command.isWWType()) { - commandBase = this._wwCommand; - } else if (command.isGlobalType()) { - commandBase = this._command; - } - - commandBase.set(name, command); - - if (command.keyMap) { - this.keyMapCommand[command.keyMap[KEYMAP_OS_INDEX]] = name; - } - - return command; - } - - /** - * _initEvent - * Bind event handler to eventManager - * @private - */ - - }, { - key: '_initEvent', - value: function _initEvent() { - var _this = this; - - this.base.eventManager.listen('command', function () { - _this.exec.apply(_this, arguments); - }); - - this.base.eventManager.listen('keyMap', function (ev) { - if (!_this._options.useCommandShortcut) { - return; - } - var command = _this.keyMapCommand[ev.keyMap]; - - if (command) { - ev.data.preventDefault(); - _this.exec(command); - } - }); - } - - /** - * Execute command - * @param {String} name Command name - * @param {*} ...args Command argument - * @returns {*} - */ - - }, { - key: 'exec', - value: function exec(name) { - var commandToRun = void 0, - result = void 0; - var context = this.base; - - commandToRun = this._command.get(name); - - if (!commandToRun) { - if (this.base.isMarkdownMode()) { - commandToRun = this._mdCommand.get(name); - context = this.base.mdEditor; - } else { - commandToRun = this._wwCommand.get(name); - context = this.base.wwEditor; - } - } - - if (commandToRun) { - var _commandToRun; - - for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - args[_key2 - 1] = arguments[_key2]; - } - - args.unshift(context); - result = (_commandToRun = commandToRun).exec.apply(_commandToRun, args); - } - - return result; - } - }]); - - return CommandManager; -}(); - -/** - * Create command by given editor type and property object - * @param {string} type Command type - * @param {{name: string, keyMap: Array}} props Property - * @returns {*} - * @static - */ - - -CommandManager.command = function (type, props) { - var command = _command2.default.factory(type, props.name, props.keyMap); - - _tuiCodeSnippet2.default.extend(command, props); - - return command; -}; - -exports.default = CommandManager; - -/***/ }), -/* 3 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.I18n = undefined; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview Implements i18n - * @author NHN FE Development Lab - */ - - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var sharedInstance = void 0; - -var DEFAULT_CODE = 'en_US'; - -/** - * Class I18n - */ - -var I18n = function () { - function I18n() { - _classCallCheck(this, I18n); - - this._code = DEFAULT_CODE; - this._langs = new _tuiCodeSnippet2.default.Map(); - } - - /** - * Set locale code - * @param {string} code locale code - */ - - - _createClass(I18n, [{ - key: 'setCode', - value: function setCode(code) { - this._code = code; - } - - /** - * Set language set - * @param {string|string[]} codes locale code - * @param {object} data language set - */ - - }, { - key: 'setLanguage', - value: function setLanguage(codes, data) { - var _this = this; - - codes = [].concat(codes); - - codes.forEach(function (code) { - if (!_this._langs.has(code)) { - _this._langs.set(code, data); - } else { - var langData = _this._langs.get(code); - _this._langs.set(code, _tuiCodeSnippet2.default.extend(langData, data)); - } - }); - } - - /** - * Get text of key - * @param {string} key key of text - * @param {string} code locale code - * @returns {string} - */ - - }, { - key: 'get', - value: function get(key, code) { - if (!code) { - code = this._code; - } - - var langSet = this._langs.get(code); - - if (!langSet) { - langSet = this._langs.get(DEFAULT_CODE); - } - - var text = langSet[key]; - - if (!text) { - throw new Error('There is no text key "' + key + '" in ' + code); - } - - return text; - } - }], [{ - key: 'getSharedInstance', - value: function getSharedInstance() { - if (!sharedInstance) { - sharedInstance = new I18n(); - } - - return sharedInstance; - } - }]); - - return I18n; -}(); - -exports.I18n = I18n; -exports.default = new I18n(); - -/***/ }), -/* 4 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview DOM Utils - * @author NHN FE Development Lab - */ -var FIND_ZWB = /\u200B/g; - -/** - * Check if node is text node - * @param {Node} node node to check - * @returns {boolean} result - * @ignore - */ -var isTextNode = function isTextNode(node) { - return node && node.nodeType === Node.TEXT_NODE; -}; - -/** - * Check if node is element node - * @param {Node} node node to check - * @returns {boolean} result - * @ignore - */ -var isElemNode = function isElemNode(node) { - return node && node.nodeType === Node.ELEMENT_NODE; -}; - -/** - * Check that the node is block node - * @param {Node} node node - * @returns {boolean} - * @ignore - */ -var isBlockNode = function isBlockNode(node) { - return (/^(ADDRESS|ARTICLE|ASIDE|BLOCKQUOTE|DETAILS|DIALOG|DD|DIV|DL|DT|FIELDSET|FIGCAPTION|FIGURE|FOOTER|FORM|H[\d]|HEADER|HGROUP|HR|LI|MAIN|NAV|OL|P|PRE|SECTION|UL)$/ig.test(this.getNodeName(node)) - ); -}; - -/** - * Get node name of node - * @param {Node} node node - * @returns {string} node name - * @ignore - */ -var getNodeName = function getNodeName(node) { - if (isElemNode(node)) { - return node.tagName; - } - - return 'TEXT'; -}; - -/** - * Get node offset length of node(for Range API) - * @param {Node} node node - * @returns {number} length - * @ignore - */ -var getTextLength = function getTextLength(node) { - var len = void 0; - - if (isElemNode(node)) { - len = node.textContent.replace(FIND_ZWB, '').length; - } else if (isTextNode(node)) { - len = node.nodeValue.replace(FIND_ZWB, '').length; - } - - return len; -}; - -/** - * Get node offset length of node(for Range API) - * @param {Node} node node - * @returns {number} length - * @ignore - */ -var getOffsetLength = function getOffsetLength(node) { - var len = void 0; - - if (isElemNode(node)) { - len = node.childNodes.length; - } else if (isTextNode(node)) { - len = node.nodeValue.replace(FIND_ZWB, '').length; - } - - return len; -}; - -/** - * get node offset between parent's childnodes - * @param {Node} node node - * @returns {number} offset(index) - * @ignore - */ -var getNodeOffsetOfParent = function getNodeOffsetOfParent(node) { - var childNodesOfParent = node.parentNode.childNodes; - var i = void 0, - t = void 0, - found = void 0; - - for (i = 0, t = childNodesOfParent.length; i < t; i += 1) { - if (childNodesOfParent[i] === node) { - found = i; - break; - } - } - - return found; -}; - -/** - * get child node by offset - * @param {Node} node node - * @param {number} index offset index - * @returns {Node} foudned node - * @ignore - */ -var getChildNodeByOffset = function getChildNodeByOffset(node, index) { - var currentNode = void 0; - - if (isTextNode(node)) { - currentNode = node; - } else if (node.childNodes.length && index >= 0) { - currentNode = node.childNodes[index]; - } - - return currentNode; -}; - -/** - * find next node from passed node - * @param {strong} direction previous or next - * @param {Node} node node - * @param {string} untilNodeName parent node name to limit - * @returns {Node} founded node - * @ignore - */ -var getNodeWithDirectionUntil = function getNodeWithDirectionUntil(direction, node, untilNodeName) { - var directionKey = direction + 'Sibling'; - var nodeName = void 0, - foundedNode = void 0; - - while (node && !node[directionKey]) { - nodeName = getNodeName(node.parentNode); - - if (nodeName === untilNodeName || nodeName === 'BODY') { - break; - } - - node = node.parentNode; - } - - if (node[directionKey]) { - foundedNode = node[directionKey]; - } - - return foundedNode; -}; - -/** - * get prev node of childnode pointed with index - * @param {Node} node node - * @param {number} index offset index - * @param {string} untilNodeName parent node name to limit - * @returns {Node} founded node - * @ignore - */ -var getPrevOffsetNodeUntil = function getPrevOffsetNodeUntil(node, index, untilNodeName) { - var prevNode = void 0; - - if (index > 0) { - prevNode = getChildNodeByOffset(node, index - 1); - } else { - prevNode = getNodeWithDirectionUntil('previous', node, untilNodeName); - } - - return prevNode; -}; - -var getParentUntilBy = function getParentUntilBy(node, matchCondition, stopCondition) { - var foundedNode = void 0; - - while (node.parentNode && !matchCondition(node.parentNode)) { - node = node.parentNode; - - if (stopCondition && stopCondition(node.parentNode)) { - break; - } - } - - if (matchCondition(node.parentNode)) { - foundedNode = node; - } - - return foundedNode; -}; - -/** - * get parent node until paseed node name - * @param {Node} node node - * @param {string|HTMLNode} untilNode node name or node to limit - * @returns {Node} founded node - * @ignore - */ -var getParentUntil = function getParentUntil(node, untilNode) { - var foundedNode = void 0; - - if (_tuiCodeSnippet2.default.isString(untilNode)) { - foundedNode = getParentUntilBy(node, function (targetNode) { - return untilNode === getNodeName(targetNode); - }); - } else { - foundedNode = getParentUntilBy(node, function (targetNode) { - return untilNode === targetNode; - }); - } - - return foundedNode; -}; - -/** - * get node on the given direction under given parent - * @param {strong} direction previous or next - * @param {Node} node node - * @param {string|Node} underNode parent node name to limit - * @returns {Node} founded node - * @ignore - */ -var getNodeWithDirectionUnderParent = function getNodeWithDirectionUnderParent(direction, node, underNode) { - var directionKey = direction + 'Sibling'; - var foundedNode = void 0; - - node = getParentUntil(node, underNode); - - if (node && node[directionKey]) { - foundedNode = node[directionKey]; - } - - return foundedNode; -}; - -/** - * get top previous top level node under given node - * @param {Node} node node - * @param {Node} underNode underNode - * @returns {Node} founded node - * @ignore - */ -var getTopPrevNodeUnder = function getTopPrevNodeUnder(node, underNode) { - return getNodeWithDirectionUnderParent('previous', node, underNode); -}; - -/** - * get next top level block node - * @param {Node} node node - * @param {Node} underNode underNode - * @returns {Node} founded node - * @ignore - */ -var getTopNextNodeUnder = function getTopNextNodeUnder(node, underNode) { - return getNodeWithDirectionUnderParent('next', node, underNode); -}; - -/** - * Get parent element the body element - * @param {Node} node Node for start searching - * @returns {Node} - * @ignore - */ -var getTopBlockNode = function getTopBlockNode(node) { - return getParentUntil(node, 'BODY'); -}; - -/** - * Get previous text node - * @param {Node} node Node for start searching - * @returns {Node} - * @ignore - */ -var getPrevTextNode = function getPrevTextNode(node) { - node = node.previousSibling || node.parentNode; - - while (!isTextNode(node) && getNodeName(node) !== 'BODY') { - if (node.previousSibling) { - node = node.previousSibling; - - while (node.lastChild) { - node = node.lastChild; - } - } else { - node = node.parentNode; - } - } - - if (getNodeName(node) === 'BODY') { - node = null; - } - - return node; -}; - -/** - * test whether root contains the given node - * @param {HTMLNode} root - root node - * @param {HTMLNode} node - node to test - * @returns {Boolean} true if root contains node - * @ignore - */ -var containsNode = function containsNode(root, node) { - var walker = document.createTreeWalker(root, 4, null, false); - var found = root === node; - - while (!found && walker.nextNode()) { - found = walker.currentNode === node; - } - - return found; -}; - -/** - * find node by offset - * @param {HTMLElement} root Root element - * @param {Array.} offsetList offset list - * @param {function} textNodeFilter Text node filter - * @returns {Array} - * @ignore - */ -var findOffsetNode = function findOffsetNode(root, offsetList, textNodeFilter) { - var result = []; - var text = ''; - var walkerOffset = 0; - var newWalkerOffset = void 0; - - if (!offsetList.length) { - return result; - } - - var offset = offsetList.shift(); - var walker = document.createTreeWalker(root, 4, null, false); - - while (walker.nextNode()) { - text = walker.currentNode.nodeValue || ''; - - if (textNodeFilter) { - text = textNodeFilter(text); - } - - newWalkerOffset = walkerOffset + text.length; - - while (newWalkerOffset >= offset) { - result.push({ - container: walker.currentNode, - offsetInContainer: offset - walkerOffset, - offset: offset - }); - - if (!offsetList.length) { - return result; - } - offset = offsetList.shift(); - } - walkerOffset = newWalkerOffset; - } - - // there should be offset left - do { - result.push({ - container: walker.currentNode, - offsetInContainer: text.length, - offset: offset - }); - offset = offsetList.shift(); - } while (!_tuiCodeSnippet2.default.isUndefined(offset)); - - return result; -}; - -var getNodeInfo = function getNodeInfo(node) { - var path = {}; - - path.tagName = node.nodeName; - - if (node.id) { - path.id = node.id; - } - - var className = node.className.trim(); - - if (className) { - path.className = className; - } - - return path; -}; - -var getPath = function getPath(node, root) { - var paths = []; - - while (node && node !== root) { - if (isElemNode(node)) { - paths.unshift(getNodeInfo(node)); - } - - node = node.parentNode; - } - - return paths; -}; - -/** - * Find next, previous TD or TH element by given TE element - * @param {HTMLElement} node TD element - * @param {string} direction 'next' or 'previous' - * @returns {HTMLElement|null} - * @ignore - */ -var getTableCellByDirection = function getTableCellByDirection(node, direction) { - var targetElement = null; - - if (!_tuiCodeSnippet2.default.isUndefined(direction) && (direction === 'next' || direction === 'previous')) { - if (direction === 'next') { - targetElement = node.nextElementSibling; - } else { - targetElement = node.previousElementSibling; - } - } - - return targetElement; -}; - -/** - * Find sibling TR's TD element by given TD and direction - * @param {HTMLElement} node TD element - * @param {string} direction Boolean value for find first TD in next line - * @param {boolean} [needEdgeCell=false] Boolean value for find first TD in next line - * @returns {HTMLElement|null} - * @ignore - */ -var getSiblingRowCellByDirection = function getSiblingRowCellByDirection(node, direction, needEdgeCell) { - var tableCellElement = null; - var $node = void 0, - index = void 0, - $targetRowElement = void 0, - $currentContainer = void 0, - $siblingContainer = void 0, - isSiblingContainerExists = void 0; - - if (!_tuiCodeSnippet2.default.isUndefined(direction) && (direction === 'next' || direction === 'previous')) { - if (node) { - $node = (0, _jquery2.default)(node); - - if (direction === 'next') { - $targetRowElement = $node.parent().next(); - $currentContainer = $node.parents('thead'); - $siblingContainer = $currentContainer[0] && $currentContainer.next(); - isSiblingContainerExists = $siblingContainer && getNodeName($siblingContainer[0]) === 'TBODY'; - - index = 0; - } else { - $targetRowElement = $node.parent().prev(); - $currentContainer = $node.parents('tbody'); - $siblingContainer = $currentContainer[0] && $currentContainer.prev(); - isSiblingContainerExists = $siblingContainer && getNodeName($siblingContainer[0]) === 'THEAD'; - - index = node.parentNode.childNodes.length - 1; - } - - if (_tuiCodeSnippet2.default.isUndefined(needEdgeCell) || !needEdgeCell) { - index = getNodeOffsetOfParent(node); - } - - if ($targetRowElement[0]) { - tableCellElement = $targetRowElement.children('td,th')[index]; - } else if ($currentContainer[0] && isSiblingContainerExists) { - tableCellElement = $siblingContainer.find('td,th')[index]; - } - } - } - - return tableCellElement; -}; - -/** - * Check that the inline node is supported by markdown - * @param {Node} node TD element - * @returns {boolean} - * @ignore - */ -var isMDSupportInlineNode = function isMDSupportInlineNode(node) { - return (/^(A|B|BR|CODE|DEL|EM|I|IMG|S|SPAN|STRONG)$/ig.test(node.nodeName) - ); -}; - -/** - * Check that node is styled node. - * Styled node is a node that has text and decorates text. - * @param {Node} node TD element - * @returns {boolean} - * @ignore - */ -var isStyledNode = function isStyledNode(node) { - return (/^(A|ABBR|ACRONYM|B|BDI|BDO|BIG|CITE|CODE|DEL|DFN|EM|I|INS|KBD|MARK|Q|S|SAMP|SMALL|SPAN|STRONG|SUB|SUP|U|VAR)$/ig.test(node.nodeName) - ); -}; - -/** - * remove node from 'start' node to 'end-1' node inside parent - * if 'end' node is null, remove all child nodes after 'start' node. - * @param {Node} parent - parent node - * @param {Node} start - start node to remove - * @param {Node} end - end node to remove - * @ignore - */ -var removeChildFromStartToEndNode = function removeChildFromStartToEndNode(parent, start, end) { - var child = start; - - if (!child || parent !== child.parentNode) { - return; - } - - while (child !== end) { - var next = child.nextSibling; - parent.removeChild(child); - child = next; - } -}; - -/** - * remove nodes along the direction from the node to reach targetParent node - * @param {Node} targetParent - stop removing when reach target parent node - * @param {Node} node - start node - * @param {boolean} isForward - direction - * @ignore - */ -var removeNodesByDirection = function removeNodesByDirection(targetParent, node, isForward) { - var parent = node; - - while (parent !== targetParent) { - var nextParent = parent.parentNode; - var _parent = parent, - nextSibling = _parent.nextSibling, - previousSibling = _parent.previousSibling; - - - if (!isForward && nextSibling) { - removeChildFromStartToEndNode(nextParent, nextSibling, null); - } else if (isForward && previousSibling) { - removeChildFromStartToEndNode(nextParent, nextParent.childNodes[0], parent); - } - - parent = nextParent; - } -}; - -var getLeafNode = function getLeafNode(node) { - var result = node; - while (result.childNodes && result.childNodes.length) { - var _result = result, - nextLeaf = _result.firstChild; - - // When inline tag have empty text node with other childnodes, ignore empty text node. - - if (isTextNode(nextLeaf) && !getTextLength(nextLeaf)) { - result = nextLeaf.nextSibling || nextLeaf; - } else { - result = nextLeaf; - } - } - - return result; -}; -/** - * check if a coordinates is inside a task box - * @param {object} style - computed style of task box - * @param {number} offsetX - event x offset - * @param {number} offsetY - event y offset - * @returns {boolean} - * @ignore - */ -var isInsideTaskBox = function isInsideTaskBox(style, offsetX, offsetY) { - var rect = { - left: parseInt(style.left, 10), - top: parseInt(style.top, 10), - width: parseInt(style.width, 10), - height: parseInt(style.height, 10) - }; - - return offsetX >= rect.left && offsetX <= rect.left + rect.width && offsetY >= rect.top && offsetY <= rect.top + rect.height; -}; - -/** - * Check whether node is OL or UL - * @param {node} node - node - * @returns {boolean} - whether node is OL or UL - * @ignore - */ -var isListNode = function isListNode(node) { - if (!node) { - return false; - } - - return node.nodeName === 'UL' || node.nodeName === 'OL'; -}; - -/** - * Check whether node is first list item - * @param {node} node - node - * @returns {boolean} whether node is first list item - * @ignore - */ -var isFirstListItem = function isFirstListItem(node) { - var nodeName = node.nodeName, - parentNode = node.parentNode; - - - return nodeName === 'LI' && node === parentNode.firstChild; -}; - -/** - * Check whether node is first level list item - * @param {node} node - node - * @returns {boolean} whether node is first level list item - * @ignore - */ -var isFirstLevelListItem = function isFirstLevelListItem(node) { - var nodeName = node.nodeName, - listNode = node.parentNode; - var listParentNode = listNode.parentNode; - - - return nodeName === 'LI' && !isListNode(listParentNode); -}; - -/** - * Merge node to target node and detach node - * @param {node} node - node - * @param {node} targetNode - target node - * @ignore - */ -var mergeNode = function mergeNode(node, targetNode) { - if (node.hasChildNodes()) { - _tuiCodeSnippet2.default.forEachArray(node.childNodes, function () { - targetNode.appendChild(node.firstChild); - }); - - targetNode.normalize(); - } - - if (node.parentNode) { - node.parentNode.removeChild(node); - } -}; - -/** - * Create hr that is not contenteditable - * @returns {node} hr is wraped div - * @ignore - */ -var createHorizontalRule = function createHorizontalRule() { - var div = document.createElement('div'); - var hr = document.createElement('hr'); - - div.setAttribute('contenteditable', false); - hr.setAttribute('contenteditable', false); - - div.appendChild(hr); - - return div; -}; - -/** - * Create Empty Line - * @returns {node}

    - * @private - */ -var createEmptyLine = function createEmptyLine() { - var div = document.createElement('div'); - div.appendChild(document.createElement('br')); - - return div; -}; - -/** - * Find same tagName child node and change wrapping order. - * For example, if below node need to optimize 'B' tag. - * test - * should be changed tag's order. - * test - * @param {node} node - * @param {string} tagName - * @returns {node} - * @private - */ -var changeTagOrder = function changeTagOrder(node, tagName) { - if (node.nodeName !== 'SPAN') { - var parentNode = node.parentNode; - - var tempNode = node; - - while (tempNode.childNodes && tempNode.childNodes.length === 1 && !isTextNode(tempNode.firstChild)) { - tempNode = tempNode.firstChild; - - if (tempNode.nodeName === 'SPAN') { - break; - } - - if (tempNode.nodeName === tagName) { - var wrapper = document.createElement(tagName); - - mergeNode(tempNode, tempNode.parentNode); - parentNode.replaceChild(wrapper, node); - wrapper.appendChild(node); - - return wrapper; - } - } - } - - return node; -}; - -/** - * Find same tagName nodes and merge from startNode to endNode. - * @param {node} startNode - * @param {node} endNode - * @param {string} tagName - * @returns {node} - * @private - */ -var mergeSameNodes = function mergeSameNodes(startNode, endNode, tagName) { - var startBlockNode = changeTagOrder(startNode, tagName); - - if (startBlockNode.nodeName === tagName) { - var endBlockNode = changeTagOrder(endNode, tagName); - var mergeTargetNode = startBlockNode; - var nextNode = startBlockNode.nextSibling; - - while (nextNode) { - var tempNext = nextNode.nextSibling; - - nextNode = changeTagOrder(nextNode, tagName); - - if (nextNode.nodeName === tagName) { - // eslint-disable-next-line max-depth - if (mergeTargetNode) { - mergeNode(nextNode, mergeTargetNode); - } else { - mergeTargetNode = nextNode; - } - } else { - mergeTargetNode = null; - } - - if (nextNode === endBlockNode) { - break; - } - - nextNode = tempNext; - } - } -}; - -/** - * Find same tagName nodes in range and merge nodes. - * For example range is like this - * AAABBB - * nodes is changed below - * AAABBB - * @param {range} range - * @param {string} tagName - * @private - */ -var optimizeRange = function optimizeRange(range, tagName) { - var collapsed = range.collapsed, - commonAncestorContainer = range.commonAncestorContainer, - startContainer = range.startContainer, - endContainer = range.endContainer; - - - if (!collapsed) { - var optimizedNode = null; - - if (startContainer !== endContainer) { - mergeSameNodes(getParentUntil(startContainer, commonAncestorContainer), getParentUntil(endContainer, commonAncestorContainer), tagName); - - optimizedNode = commonAncestorContainer; - } else if (isTextNode(startContainer)) { - optimizedNode = startContainer.parentNode; - } - - if (optimizedNode && optimizedNode.nodeName === tagName) { - var _optimizedNode = optimizedNode, - previousSibling = _optimizedNode.previousSibling; - - var tempNode = void 0; - - if (previousSibling) { - tempNode = changeTagOrder(previousSibling); - - if (tempNode.nodeName === tagName) { - mergeNode(optimizedNode, tempNode); - } - } - - var _optimizedNode2 = optimizedNode, - nextSibling = _optimizedNode2.nextSibling; - - - if (nextSibling) { - tempNode = changeTagOrder(nextSibling); - - if (tempNode.nodeName === tagName) { - mergeNode(tempNode, optimizedNode); - } - } - } - } -}; - -/** - * Gets all text node from root element. - * @param {HTMLElement} root Root element - * @returns {Array} list of text nodes - * @ignore - */ -var getAllTextNode = function getAllTextNode(root) { - var walker = document.createTreeWalker(root, 4, null, false); - var result = []; - - while (walker.nextNode()) { - var node = walker.currentNode; - - if (isTextNode(node)) { - result.push(node); - } - } - - return result; -}; - -/** - * Check whether the node is 'TD' or 'TH' - * @param {HTMLElement} node - the target node - * @returns {boolean} - whether the node is 'TD' or 'TH' - * @ignore - */ -var isCellNode = function isCellNode(node) { - if (!node) { - return false; - } - - return node.nodeName === 'TD' || node.nodeName === 'TH'; -}; - -/** - * Get the last node on the target node by the condition - * @param {HTMLElement} node - the target node - * @returns {function} - the condition to find the node - * @ignore - */ -var getLastNodeBy = function getLastNodeBy(node, condition) { - var lastNode = node && node.lastChild; - - while (lastNode && condition(lastNode)) { - lastNode = lastNode.lastChild; - } - - return lastNode; -}; - -/** - * Get the parent node on the target node by the condition - * @param {HTMLElement} node - the target node - * @returns {function} - the condition to find the node - * @ignore - */ -var getParentNodeBy = function getParentNodeBy(node, condition) { - while (node && condition(node.parentNode, node)) { - node = node.parentNode; - } - - return node; -}; - -/** - * Get the sibling node on the target node by the condition - * @param {HTMLElement} node - the target node - * @param {string} direction - the direction to find node ('previous', 'next') - * @returns {function} - the condition to find the node - * @ignore - */ -var getSiblingNodeBy = function getSiblingNodeBy(node, direction, condition) { - var directionKey = direction + 'Sibling'; - - while (node && condition(node[directionKey], node)) { - node = node[directionKey]; - } - - return node; -}; - -exports.default = { - getNodeName: getNodeName, - isTextNode: isTextNode, - isElemNode: isElemNode, - isBlockNode: isBlockNode, - getTextLength: getTextLength, - getOffsetLength: getOffsetLength, - getPrevOffsetNodeUntil: getPrevOffsetNodeUntil, - getNodeOffsetOfParent: getNodeOffsetOfParent, - getChildNodeByOffset: getChildNodeByOffset, - getNodeWithDirectionUntil: getNodeWithDirectionUntil, - containsNode: containsNode, - getTopPrevNodeUnder: getTopPrevNodeUnder, - getTopNextNodeUnder: getTopNextNodeUnder, - getParentUntilBy: getParentUntilBy, - getParentUntil: getParentUntil, - getTopBlockNode: getTopBlockNode, - getPrevTextNode: getPrevTextNode, - findOffsetNode: findOffsetNode, - getPath: getPath, - getNodeInfo: getNodeInfo, - getTableCellByDirection: getTableCellByDirection, - getSiblingRowCellByDirection: getSiblingRowCellByDirection, - isMDSupportInlineNode: isMDSupportInlineNode, - isStyledNode: isStyledNode, - removeChildFromStartToEndNode: removeChildFromStartToEndNode, - removeNodesByDirection: removeNodesByDirection, - getLeafNode: getLeafNode, - isInsideTaskBox: isInsideTaskBox, - isListNode: isListNode, - isFirstListItem: isFirstListItem, - isFirstLevelListItem: isFirstLevelListItem, - mergeNode: mergeNode, - createHorizontalRule: createHorizontalRule, - createEmptyLine: createEmptyLine, - changeTagOrder: changeTagOrder, - mergeSameNodes: mergeSameNodes, - optimizeRange: optimizeRange, - getAllTextNode: getAllTextNode, - isCellNode: isCellNode, - getLastNodeBy: getLastNodeBy, - getParentNodeBy: getParentNodeBy, - getSiblingNodeBy: getSiblingNodeBy -}; - -/***/ }), -/* 5 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -/** -* @fileoverview Editor/Viewer proxy for extensions -* @author NHN FE Development Lab -*/ -/* eslint global-require: 0 no-empty: 0 */ - -var Editor = void 0; -try { - Editor = __webpack_require__(30); -} catch (e) {} -if (!Editor) { - try { - Editor = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module '../viewer'"); e.code = 'MODULE_NOT_FOUND'; throw e; }())); - } catch (e) {} -} - -exports.default = Editor; - -/***/ }), -/* 6 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createTableData = createTableData; -exports.createCellIndexData = createCellIndexData; - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Parse cell like td or th. - * @param {HTMLElement} cell - cell element like td or th - * @param {number} rowIndex - row index - * @param {number} colIndex - column index - * @returns {{ - * nodeName: string, - * colspan: number, - * rowspan: number, - * content: string, - * align: ?string - * }} - * @private - */ -/** -* @fileoverview Implements tableDataHandler -* @author NHN FE Development Lab -*/ -function _parseCell(cell, rowIndex, colIndex) { - var $cell = (0, _jquery2.default)(cell); - var colspan = $cell.attr('colspan'); - var rowspan = $cell.attr('rowspan'); - var nodeName = cell.nodeName; - - - if (nodeName !== 'TH' && nodeName !== 'TD') { - return null; - } - - var cellData = { - nodeName: cell.nodeName, - colspan: colspan ? parseInt(colspan, 10) : 1, - rowspan: rowspan ? parseInt(rowspan, 10) : 1, - content: $cell.html(), - elementIndex: { - rowIndex: rowIndex, - colIndex: colIndex - } - }; - - if (cell.nodeName === 'TH' && cell.align) { - cellData.align = cell.align; - } - - return cellData; -} - -/** - * Add merged cell. - * @param {object} base - base table data - * @param {object} cellData - cell data - * @param {number} startRowIndex - start row index - * @param {number} startCellIndex - start cell index - * @private - */ -function _addMergedCell(base, cellData, startRowIndex, startCellIndex) { - var colspan = cellData.colspan, - rowspan = cellData.rowspan, - nodeName = cellData.nodeName; - - var colMerged = colspan > 1; - var rowMerged = rowspan > 1; - - if (!colMerged && !rowMerged) { - return; - } - - var limitRowIndex = startRowIndex + rowspan; - var limitCellIndex = startCellIndex + colspan; - - _tuiCodeSnippet2.default.range(startRowIndex, limitRowIndex).forEach(function (rowIndex) { - base[rowIndex] = base[rowIndex] || []; - - _tuiCodeSnippet2.default.range(startCellIndex, limitCellIndex).forEach(function (cellIndex) { - var mergedData = { - nodeName: nodeName - }; - - if (rowIndex === startRowIndex && cellIndex === startCellIndex) { - return; - } - - if (colMerged) { - mergedData.colMergeWith = startCellIndex; - } - - if (rowMerged) { - mergedData.rowMergeWith = startRowIndex; - } - - base[rowIndex][cellIndex] = mergedData; - }); - }); -} - -/** - * Create table data from jQuery table Element. - * @param {jQuery} $table - jQuery table element - * @returns {Array.>} - * @ignore - */ -function createTableData($table) { - var tableData = []; - - $table.find('tr').each(function (rowIndex, tr) { - var stackedColCount = 0; - - tableData[rowIndex] = tableData[rowIndex] || []; - - (0, _jquery2.default)(tr).children().each(function (colIndex, cell) { - var cellData = _parseCell(cell, rowIndex, colIndex); - - if (!cellData) { - return; - } - var dataColIndex = colIndex + stackedColCount; - - while (tableData[rowIndex][dataColIndex]) { - dataColIndex += 1; - stackedColCount += 1; - } - - tableData[rowIndex][dataColIndex] = cellData; - _addMergedCell(tableData, cellData, rowIndex, dataColIndex); - }); - }); - - if ($table[0].className) { - tableData.className = $table[0].className; - } - - return tableData; -} - -/** - * Create cell index data of table data. - * @param {Array.>} tableData - table data - * @returns {Array.>} - * @ignore - */ -function createCellIndexData(tableData) { - var mappingData = []; - - tableData.forEach(function (row, rowIndex) { - var mappingRow = []; - - row.forEach(function (cell, colIndex) { - if (_tuiCodeSnippet2.default.isUndefined(cell.colMergeWith) && _tuiCodeSnippet2.default.isUndefined(cell.rowMergeWith)) { - mappingRow.push({ - rowIndex: rowIndex, - colIndex: colIndex - }); - } - }); - mappingData.push(mappingRow); - }); - - return mappingData; -} - -/** - * Get header aligns. - * @param {Array.>} tableData - table data - * @returns {Array.} - * @private - */ -function _getHeaderAligns(tableData) { - var headRowData = tableData[0]; - - - return headRowData.map(function (cellData) { - var align = void 0; - - if (_tuiCodeSnippet2.default.isExisty(cellData.colMergeWith)) { - align = headRowData[cellData.colMergeWith].align; - } else { - align = cellData.align; - } - - return align; - }); -} - -/** - * Create render data. - * @param {Array.} tableData - table data - * @param {Array.} cellIndexData - cell index data - * @returns {Array.>} - * @ignore - */ -function createRenderData(tableData, cellIndexData) { - var headerAligns = _getHeaderAligns(tableData); - var renderData = cellIndexData.map(function (row) { - return row.map(function (_ref) { - var rowIndex = _ref.rowIndex, - colIndex = _ref.colIndex; - return _tuiCodeSnippet2.default.extend({ - align: headerAligns[colIndex] - }, tableData[rowIndex][colIndex]); - }); - }); - - if (tableData.className) { - renderData.className = tableData.className; - } - - return renderData; -} - -var BASIC_CELL_CONTENT = _tuiCodeSnippet2.default.browser.msie ? '' : '
    '; - -/** - * Create basic cell data. - * @param {number} rowIndex - row index - * @param {number} colIndex - column index - * @param {string} nodeName - node name - * @returns {{ - * nodeName: string, - * colspan: number, - * rowspan: number, - * content: string - * }} - * @ignore - */ -function createBasicCell(rowIndex, colIndex, nodeName) { - return { - nodeName: nodeName || 'TD', - colspan: 1, - rowspan: 1, - content: BASIC_CELL_CONTENT, - elementIndex: { - rowIndex: rowIndex, - colIndex: colIndex - } - }; -} - -/** - * Find element row index. - * @param {jQuery} $cell - cell jQuery element like td or th - * @returns {number} - * @ignore - */ -function findElementRowIndex($cell) { - var $tr = $cell.closest('tr'); - var rowIndex = $tr.prevAll().length; - - if ($tr.parent()[0].nodeName === 'TBODY') { - rowIndex += 1; - } - - return rowIndex; -} - -/** - * Find element col index. - * @param {jQuery} $cell - cell jQuery element like td or th - * @returns {number} - * @ignore - */ -function findElementColIndex($cell) { - return $cell.closest('td, th').prevAll().length; -} - -/** - * Find indexes of base table data from mappin data. - * @param {Array.>} cellIndexData - cell index data - * @param {jQuery} $cell - cell jQuery element like td or th - * @returns {{rowIndex: number, cellIndex: number}} - * @ignore - */ -function findCellIndex(cellIndexData, $cell) { - var elementRowIndex = findElementRowIndex($cell); - var elementColIndex = findElementColIndex($cell); - - return cellIndexData[elementRowIndex][elementColIndex]; -} - -/** - * Find last index of col merged cells. - * @param {Array.>} tableData - tableData data - * @param {number} rowIndex - row index of base data - * @param {number} colIndex - column index of tabld data - * @returns {number} - * @ignore - */ -function findRowMergedLastIndex(tableData, rowIndex, colIndex) { - var cellData = tableData[rowIndex][colIndex]; - var foundRowIndex = rowIndex; - - if (cellData.rowspan > 1) { - foundRowIndex += cellData.rowspan - 1; - } - - return foundRowIndex; -} - -/** - * Find last index of col merged cells. - * @param {Array.>} tableData - tableData data - * @param {number} rowIndex - row index of base data - * @param {number} colIndex - column index of tabld data - * @returns {number} - * @ignore - */ -function findColMergedLastIndex(tableData, rowIndex, colIndex) { - var cellData = tableData[rowIndex][colIndex]; - var foundColIndex = colIndex; - - if (cellData.colspan > 1) { - foundColIndex += cellData.colspan - 1; - } - - return foundColIndex; -} - -/** - * Find cell element index. - * @param {Array.>} tableData - tableData data - * @param {number} rowIndex - row index of base data - * @param {number} colIndex - col index of base data - * @returns {{rowIndex: number, colIndex: number}} - * @ignore - */ -function findElementIndex(tableData, rowIndex, colIndex) { - var cellData = tableData[rowIndex][colIndex]; - - rowIndex = _tuiCodeSnippet2.default.isExisty(cellData.rowMergeWith) ? cellData.rowMergeWith : rowIndex; - colIndex = _tuiCodeSnippet2.default.isExisty(cellData.colMergeWith) ? cellData.colMergeWith : colIndex; - - return tableData[rowIndex][colIndex].elementIndex; -} - -/** - * Stuff cells into incomplete row. - * @param {Array.>} tableData - table data - * @param {number} limitIndex - limit index - * @ignore - */ -function stuffCellsIntoIncompleteRow(tableData, limitIndex) { - tableData.forEach(function (rowData, rowIndex) { - var startIndex = rowData.length; - if (startIndex) { - var nodeName = rowData[0].nodeName; - - - _tuiCodeSnippet2.default.range(startIndex, limitIndex).forEach(function (colIndex) { - rowData.push(createBasicCell(rowIndex, colIndex, nodeName)); - }); - } - }); -} - -/** - * Add tbody or thead of table data if need. - * @param {Array.>} tableData - table data - * @returns {boolean} - * @ignore - */ -function addTbodyOrTheadIfNeed(tableData) { - var header = tableData[0]; - - var cellCount = header.length; - var added = true; - - if (!cellCount && tableData[1]) { - _tuiCodeSnippet2.default.range(0, tableData[1].length).forEach(function (colIndex) { - header.push(createBasicCell(0, colIndex, 'TH')); - }); - } else if (tableData[0][0].nodeName !== 'TH') { - var _ref2; - - var newHeader = _tuiCodeSnippet2.default.range(0, cellCount).map(function (colIndex) { - return createBasicCell(0, colIndex, 'TH'); - }); - - (_ref2 = []).concat.apply(_ref2, tableData).forEach(function (cellData) { - if (cellData.elementIndex) { - cellData.elementIndex.rowIndex += 1; - } - }); - - tableData.unshift(newHeader); - } else if (tableData.length === 1) { - var newRow = _tuiCodeSnippet2.default.range(0, cellCount).map(function (colIndex) { - return createBasicCell(1, colIndex, 'TD'); - }); - - tableData.push(newRow); - } else { - added = false; - } - - return added; -} - -exports.default = { - createTableData: createTableData, - createCellIndexData: createCellIndexData, - createRenderData: createRenderData, - findElementRowIndex: findElementRowIndex, - findElementColIndex: findElementColIndex, - findCellIndex: findCellIndex, - createBasicCell: createBasicCell, - findRowMergedLastIndex: findRowMergedLastIndex, - findColMergedLastIndex: findColMergedLastIndex, - findElementIndex: findElementIndex, - stuffCellsIntoIncompleteRow: stuffCellsIntoIncompleteRow, - addTbodyOrTheadIfNeed: addTbodyOrTheadIfNeed -}; - -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _uicontroller = __webpack_require__(14); - -var _uicontroller2 = _interopRequireDefault(_uicontroller); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements LayerPopup - * @author NHN FE Development Lab - */ - - -var CLASS_PREFIX = 'tui-popup-'; -var CLASS_FIT_WINDOW = 'fit-window'; - -var LAYOUT_TEMPLATE_MODELESS = '
    \n \n
    \n \n
    \n
    \n
    '; - -var LAYOUT_TEMPLATE_MODAL = '
    \n
    \n \n
    \n \n
    \n
    \n
    \n
    '; - -/** - * A number, or a string containing a number. - * @typedef {object} LayerPopupOption - * @property {string[]} [openerCssQuery] - Css Query list to bind clickevent that open popup - * @property {string[]} [closerCssQuery] - Css Query list to bind clickevent that close popup - * @property {jQuery} $el - popup root element - * @property {jQuery|string} [content] - popup content that html string or jQuery element - * @property {string} [textContent] - popup text content - * @property {string} title - popup title - * @property {boolean} [header] - whether to draw header - * @property {jQuery} [$target] - element to append popup - * @property {boolean} modal - true: modal, false: modeless - * @property {string} [headerButtons] - replace header(close) button - */ - -/** - * Class LayerPopup - * @param {LayerPopupOption} options - popup option - */ - -var LayerPopup = function (_UIController) { - _inherits(LayerPopup, _UIController); - - function LayerPopup(options) { - _classCallCheck(this, LayerPopup); - - options = _tuiCodeSnippet2.default.extend({ - header: true, - $target: (0, _jquery2.default)('body'), - textContent: '' - }, options); - - var _this = _possibleConstructorReturn(this, (LayerPopup.__proto__ || Object.getPrototypeOf(LayerPopup)).call(this, { - tagName: 'div', - className: options.modal ? CLASS_PREFIX + 'modal-background' : CLASS_PREFIX + 'wrapper', - rootElement: options.$el - })); - - _this._initInstance(options); - _this._initDOM(options); - _this._initDOMEvent(options); - _this._initEditorEvent(options); - return _this; - } - - /** - * init instance. - * store properties & prepare before initialize DOM - * @param {LayerPopupOption} options - layer popup options - * @private - */ - - - _createClass(LayerPopup, [{ - key: '_initInstance', - value: function _initInstance(options) { - this._$target = options.$target; - - if (options.$el) { - this.$el = options.$el; - this._isExternalHtmlUse = true; - } - - if (options.content) { - this.$content = (0, _jquery2.default)(options.content); - } else { - this.$content = options.textContent; - } - - this.options = options; - } - - /** - * initialize DOM, render popup - * @private - */ - - }, { - key: '_initDOM', - value: function _initDOM() { - this._initLayout(); - - if (!this._isExternalHtmlUse) { - if (_tuiCodeSnippet2.default.isExisty(this.options.title)) { - this.setTitle(this.options.title); - } - this.setContent(this.$content); - } - - var buttons = this.options.headerButtons; - if (buttons) { - this.$el.find('.' + CLASS_PREFIX + 'close-button').remove(); - - var $buttonWrapper = this.$el.find('.' + CLASS_PREFIX + 'header-buttons'); - $buttonWrapper.empty(); - $buttonWrapper.append((0, _jquery2.default)(buttons)); - } - - if (this.options.css) { - this.$el.css(this.options.css); - } - } - - /** - * bind DOM events - * @private - */ - - }, { - key: '_initDOMEvent', - value: function _initDOMEvent() { - var _this2 = this; - - var _options = this.options, - openerCssQuery = _options.openerCssQuery, - closerCssQuery = _options.closerCssQuery; - - if (openerCssQuery) { - (0, _jquery2.default)(openerCssQuery).on('click.' + this._id, function () { - return _this2.show(); - }); - } - if (closerCssQuery) { - (0, _jquery2.default)(closerCssQuery).on('click.' + this._id, function () { - return _this2.hide(); - }); - } - - this.on('click .' + CLASS_PREFIX + 'close-button', function () { - return _this2.hide(); - }); - } - - /** - * bind editor events - * @private - * @abstract - */ - - }, { - key: '_initEditorEvent', - value: function _initEditorEvent() {} - }, { - key: '_initLayout', - value: function _initLayout() { - var options = this.options; - - - if (!this._isExternalHtmlUse) { - var layout = options.modal ? LAYOUT_TEMPLATE_MODAL : LAYOUT_TEMPLATE_MODELESS; - this.$el.html(layout); - this.$el.addClass(options.className); - this.hide(); - this._$target.append(this.$el); - this.$body = this.$el.find('.' + CLASS_PREFIX + 'body'); - - if (!options.header) { - this.$el.find('.' + CLASS_PREFIX + 'header').remove(); - } - } else { - this.hide(); - this._$target.append(this.$el); - } - } - - /** - * set popup content - * @param {jQuery|HTMLElement|string} $content - content - */ - - }, { - key: 'setContent', - value: function setContent($content) { - this.$body.empty(); - this.$body.append($content); - } - - /** - * set title - * @param {string} title - title text - */ - - }, { - key: 'setTitle', - value: function setTitle(title) { - var $title = this.$el.find('.' + CLASS_PREFIX + 'title'); - - $title.empty(); - $title.append(title); - } - - /** - * get title element - * @returns {HTMLElement} - title html element - */ - - }, { - key: 'getTitleElement', - value: function getTitleElement() { - return this.$el.find('.' + CLASS_PREFIX + 'title').get(0); - } - - /** - * hide popup - */ - - }, { - key: 'hide', - value: function hide() { - this.$el.css('display', 'none'); - this._isShow = false; - this.trigger('hidden', this); - } - - /** - * show popup - */ - - }, { - key: 'show', - value: function show() { - this.$el.css('display', 'block'); - this._isShow = true; - this.trigger('shown', this); - } - - /** - * whether this popup is visible - * @returns {boolean} - true: shown, false: hidden - */ - - }, { - key: 'isShow', - value: function isShow() { - return this._isShow; - } - - /** - * remove popup content - */ - - }, { - key: 'remove', - value: function remove() { - var _options2 = this.options, - openerCssQuery = _options2.openerCssQuery, - closerCssQuery = _options2.closerCssQuery; - - - this.trigger('remove', this); - this.off(); - - if (openerCssQuery) { - (0, _jquery2.default)(openerCssQuery).off('.' + this._id); - } - if (closerCssQuery) { - (0, _jquery2.default)(closerCssQuery).off('.' + this._id); - } - - this.$el.remove(); - this.$el = null; - } - - /** - * make popup size fit to window - * @param {boolean} fit - true to make popup fit to window - * @protected - * @ignore - */ - - }, { - key: 'setFitToWindow', - value: function setFitToWindow(fit) { - this.$el.toggleClass(CLASS_FIT_WINDOW, fit); - } - - /** - * make popup size fit to window - * @returns {boolean} - true for fit to window - * @protected - * @ignore - */ - - }, { - key: 'isFitToWindow', - value: function isFitToWindow() { - return this.$el.hasClass(CLASS_FIT_WINDOW); - } - - /** - * toggle size fit to window - * @returns {boolean} - true for fit to window - * @protected - * @ignore - */ - - }, { - key: 'toggleFitToWindow', - value: function toggleFitToWindow() { - var fitToWindow = !this.isFitToWindow(); - this.setFitToWindow(fitToWindow); - - return fitToWindow; - } - }]); - - return LayerPopup; -}(_uicontroller2.default); - -exports.default = LayerPopup; - -/***/ }), -/* 8 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tableDataHandler = __webpack_require__(6); - -var _tableDataHandler2 = _interopRequireDefault(_tableDataHandler); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Create cell html. - * @param {object} cell - cell data of table base data - * @returns {string} - * @private - */ -/** -* @fileoverview Implements tableRenderer -* @author NHN FE Development Lab -*/ -function _createCellHtml(cell) { - var attrs = cell.colspan > 1 ? ' colspan="' + cell.colspan + '"' : ''; - attrs += cell.rowspan > 1 ? ' rowspan="' + cell.rowspan + '"' : ''; - attrs += cell.align ? ' align="' + cell.align + '"' : ''; - - return '<' + cell.nodeName + attrs + '>' + cell.content + ''; -} - -/** - * Create html for thead or tbody. - * @param {Array.>} trs - tr list - * @param {string} wrapperNodeName - wrapper node name like THEAD, TBODY - * @returns {string} - * @private - */ -function _createTheadOrTbodyHtml(trs, wrapperNodeName) { - var html = ''; - - if (trs.length) { - html = trs.map(function (tr) { - var tdHtml = tr.map(_createCellHtml).join(''); - - return '' + tdHtml + ''; - }).join(''); - html = '<' + wrapperNodeName + '>' + html + ''; - } - - return html; -} - -/** - * Create table html. - * @param {Array.>} renderData - table data for render - * @returns {string} - * @private - */ -function createTableHtml(renderData) { - var thead = renderData[0] ? [renderData[0]] : []; - var tbody = renderData.slice(1); - var theadHtml = _createTheadOrTbodyHtml(thead, 'THEAD'); - var tbodyHtml = _createTheadOrTbodyHtml(tbody, 'TBODY'); - var className = renderData.className ? ' class="' + renderData.className + '"' : ''; - - return '' + (theadHtml + tbodyHtml) + ''; -} - -/** - * Replace table. - * @param {jQuery} $table - table jQuery element - * @param {Array.>} tableData - table data - * @returns {jQuery} - * @ignore - */ -function replaceTable($table, tableData) { - var cellIndexData = _tableDataHandler2.default.createCellIndexData(tableData); - var renderData = _tableDataHandler2.default.createRenderData(tableData, cellIndexData); - var $newTable = (0, _jquery2.default)(createTableHtml(renderData)); - - $table.replaceWith($newTable); - - return $newTable; -} - -/** - * Focus to cell. - * @param {squireext} sq - squire instance - * @param {range} range - range object - * @param {HTMLElement} targetCell - cell element for focus - * @ignore - */ -function focusToCell(sq, range, targetCell) { - range.selectNodeContents(targetCell); - range.collapse(true); - sq.setSelection(range); -} - -exports.default = { - createTableHtml: createTableHtml, - replaceTable: replaceTable, - focusToCell: focusToCell -}; - -/***/ }), -/* 9 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _tableDataHandler = __webpack_require__(6); - -var _tableDataHandler2 = _interopRequireDefault(_tableDataHandler); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Find unmerged table range. - * @param {Array.>} tableData - table data - * @param {jQuery} $start - start talbe cell jQuery element - * @param {jQuery} $end - end table cell jQuery element - * @returns {{ - * start: {rowIndex: number, colIndex: number}, - * end: {rowIndex: number, colIndex: number} - * }} - * @private - */ -function _findUnmergedRange(tableData, $start, $end) { - var cellIndexData = _tableDataHandler2.default.createCellIndexData(tableData); - var startCellIndex = _tableDataHandler2.default.findCellIndex(cellIndexData, $start); - var endCellIndex = _tableDataHandler2.default.findCellIndex(cellIndexData, $end); - var startRowIndex = void 0, - endRowIndex = void 0, - startColIndex = void 0, - endColIndex = void 0; - - if (startCellIndex.rowIndex > endCellIndex.rowIndex) { - startRowIndex = endCellIndex.rowIndex; - endRowIndex = startCellIndex.rowIndex; - } else { - startRowIndex = startCellIndex.rowIndex; - endRowIndex = endCellIndex.rowIndex; - } - - if (startCellIndex.colIndex > endCellIndex.colIndex) { - startColIndex = endCellIndex.colIndex; - endColIndex = startCellIndex.colIndex; - } else { - startColIndex = startCellIndex.colIndex; - endColIndex = endCellIndex.colIndex; - } - - return { - start: { - rowIndex: startRowIndex, - colIndex: startColIndex - }, - end: { - rowIndex: endRowIndex, - colIndex: endColIndex - } - }; -} - -/** - * Expand table range by row merge properties like rowspan, rowMergeWith. - * @param {Array.>} tableData - table data - * @param {{ - * start: {rowIndex: number, colIndex: number}, - * end: {rowIndex: number, colIndex: number} - * }} tableRange - table range - * @param {string} rangeType - range type like start, end - * @private - */ -/** -* @fileoverview Implements tableRangeHandler -* @author NHN FE Development Lab -*/ -function _expandRowMergedRange(tableData, tableRange, rangeType) { - var rowIndex = tableRange[rangeType].rowIndex; - - var rowData = tableData[rowIndex]; - - _tuiCodeSnippet2.default.range(tableRange.start.colIndex, tableRange.end.colIndex + 1).forEach(function (colIndex) { - var cellData = rowData[colIndex]; - var rowMergeWith = cellData.rowMergeWith; - - var lastRowMergedIndex = -1; - - if (_tuiCodeSnippet2.default.isExisty(rowMergeWith)) { - if (rowMergeWith < tableRange.start.rowIndex) { - tableRange.start.rowIndex = rowMergeWith; - } - - lastRowMergedIndex = rowMergeWith + tableData[rowMergeWith][colIndex].rowspan - 1; - } else if (cellData.rowspan > 1) { - lastRowMergedIndex = rowIndex + cellData.rowspan - 1; - } - - if (lastRowMergedIndex > tableRange.end.rowIndex) { - tableRange.end.rowIndex = lastRowMergedIndex; - } - }); -} - -/** - * Expand table range by column merge properties like colspan, colMergeWith. - * @param {Array.>} tableData - table data - * @param {{ - * start: {rowIndex: number, colIndex: number}, - * end: {rowIndex: number, colIndex: number} - * }} tableRange - table range - * @param {number} rowIndex - row index - * @param {number} colIndex - column index - * @private - */ -function _expandColMergedRange(tableData, tableRange, rowIndex, colIndex) { - var rowData = tableData[rowIndex]; - var cellData = rowData[colIndex]; - var colMergeWith = cellData.colMergeWith; - - var lastColMergedIndex = -1; - - if (_tuiCodeSnippet2.default.isExisty(colMergeWith)) { - if (colMergeWith < tableRange.start.colIndex) { - tableRange.start.colIndex = colMergeWith; - } - - lastColMergedIndex = colMergeWith + rowData[colMergeWith].colspan - 1; - } else if (cellData.colspan > 1) { - lastColMergedIndex = colIndex + cellData.colspan - 1; - } - - if (lastColMergedIndex > tableRange.end.colIndex) { - tableRange.end.colIndex = lastColMergedIndex; - } -} - -/** - * Expand table range by merge properties like colspan, rowspan. - * @param {Array.>} tableData - table data - * @param {{ - * start: {rowIndex: number, colIndex: number}, - * end: {rowIndex: number, colIndex: number} - * }} tableRange - table range - * @returns {{ - * start: {rowIndex: number, colIndex: number}, - * end: {rowIndex: number, colIndex: number} - * }} - * @private - */ -function _expandMergedRange(tableData, tableRange) { - var rangeStr = ''; - - while (rangeStr !== JSON.stringify(tableRange)) { - rangeStr = JSON.stringify(tableRange); - - _expandRowMergedRange(tableData, tableRange, 'start'); - _expandRowMergedRange(tableData, tableRange, 'end'); - - _tuiCodeSnippet2.default.range(tableRange.start.rowIndex, tableRange.end.rowIndex + 1).forEach(function (rowIndex) { - _expandColMergedRange(tableData, tableRange, rowIndex, tableRange.start.colIndex); - _expandColMergedRange(tableData, tableRange, rowIndex, tableRange.end.colIndex); - }); - } - - return tableRange; -} - -/** - * Find table range for selection. - * @param {Array.>} tableData - table data - * @param {jQuery} $start - start jQuery element - * @param {jQuery} $end - end jQuery element - * @returns {{ - * start: {rowIndex: number, colIndex: number}, - * end: {rowIndex: number, colIndex: number} - * }} - * @ignore - */ -function findSelectionRange(tableData, $start, $end) { - var unmergedRange = _findUnmergedRange(tableData, $start, $end); - - return _expandMergedRange(tableData, unmergedRange); -} - -/** - * Get table selection range. - * @param {Array.>} tableData - table data - * @param {jQuery} $selectedCells - selected cells jQuery elements - * @param {jQuery} $startContainer - start container jQuery element of text range - * @returns {{ - * start: {rowIndex: number, colIndex: number}, - * end: {rowIndex: number, colIndex: number} - *}} - * @ignore - */ -function getTableSelectionRange(tableData, $selectedCells, $startContainer) { - var cellIndexData = _tableDataHandler2.default.createCellIndexData(tableData); - var tableRange = {}; - - if ($selectedCells.length) { - var startRange = _tableDataHandler2.default.findCellIndex(cellIndexData, $selectedCells.first()); - var endRange = _tuiCodeSnippet2.default.extend({}, startRange); - - $selectedCells.each(function (index, cell) { - var cellIndex = _tableDataHandler2.default.findCellIndex(cellIndexData, (0, _jquery2.default)(cell)); - var cellData = tableData[cellIndex.rowIndex][cellIndex.colIndex]; - var lastRowMergedIndex = cellIndex.rowIndex + cellData.rowspan - 1; - var lastColMergedIndex = cellIndex.colIndex + cellData.colspan - 1; - - endRange.rowIndex = Math.max(endRange.rowIndex, lastRowMergedIndex); - endRange.colIndex = Math.max(endRange.colIndex, lastColMergedIndex); - }); - - tableRange.start = startRange; - tableRange.end = endRange; - } else { - var cellIndex = _tableDataHandler2.default.findCellIndex(cellIndexData, $startContainer); - - tableRange.start = cellIndex; - tableRange.end = _tuiCodeSnippet2.default.extend({}, cellIndex); - } - - return tableRange; -} - -exports.default = { - findSelectionRange: findSelectionRange, - getTableSelectionRange: getTableSelectionRange -}; - -/***/ }), -/* 10 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE__10__; - -/***/ }), -/* 11 */ -/***/ (function(module, exports) { - -var g; - -// This works in non-strict mode -g = (function() { - return this; -})(); - -try { - // This works if eval is allowed (see CSP) - g = g || new Function("return this")(); -} catch (e) { - // This works if the window reference is available - if (typeof window === "object") g = window; -} - -// g can still be undefined, but nothing to do about it... -// We return undefined, instead of nothing here, so it's -// easier to handle this case. if(!global) { ...} - -module.exports = g; - - -/***/ }), -/* 12 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// a duplex stream is just a stream that is both readable and writable. -// Since JS doesn't have multiple prototypal inheritance, this class -// prototypally inherits from Readable, and then parasitically from -// Writable. - - - -/**/ - -var pna = __webpack_require__(19); -/**/ - -/**/ -var objectKeys = Object.keys || function (obj) { - var keys = []; - for (var key in obj) { - keys.push(key); - }return keys; -}; -/**/ - -module.exports = Duplex; - -/**/ -var util = __webpack_require__(16); -util.inherits = __webpack_require__(13); -/**/ - -var Readable = __webpack_require__(48); -var Writable = __webpack_require__(29); - -util.inherits(Duplex, Readable); - -{ - // avoid scope creep, the keys array can then be collected - var keys = objectKeys(Writable.prototype); - for (var v = 0; v < keys.length; v++) { - var method = keys[v]; - if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; - } -} - -function Duplex(options) { - if (!(this instanceof Duplex)) return new Duplex(options); - - Readable.call(this, options); - Writable.call(this, options); - - if (options && options.readable === false) this.readable = false; - - if (options && options.writable === false) this.writable = false; - - this.allowHalfOpen = true; - if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; - - this.once('end', onend); -} - -Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function () { - return this._writableState.highWaterMark; - } -}); - -// the no-half-open enforcer -function onend() { - // if we allow half-open state, or if the writable side ended, - // then we're ok. - if (this.allowHalfOpen || this._writableState.ended) return; - - // no more data can be written. - // But allow more writes to happen in this tick. - pna.nextTick(onEndNT, this); -} - -function onEndNT(self) { - self.end(); -} - -Object.defineProperty(Duplex.prototype, 'destroyed', { - get: function () { - if (this._readableState === undefined || this._writableState === undefined) { - return false; - } - return this._readableState.destroyed && this._writableState.destroyed; - }, - set: function (value) { - // we ignore the value if the stream - // has not been initialized yet - if (this._readableState === undefined || this._writableState === undefined) { - return; - } - - // backward compatibility, the user is explicitly - // managing destroyed - this._readableState.destroyed = value; - this._writableState.destroyed = value; - } -}); - -Duplex.prototype._destroy = function (err, cb) { - this.push(null); - this.end(); - - pna.nextTick(cb, err); -}; - -/***/ }), -/* 13 */ -/***/ (function(module, exports) { - -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - if (superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }) - } - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - if (superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } - } -} - - -/***/ }), -/* 14 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview Implements ui controller - * @author NHN FE Development Lab - */ - - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var _uiInstanceId = -1; - -/** - * get ui instance id - * @returns {number} - new instance id - * @ignore - */ -function makeUIInstanceId() { - _uiInstanceId += 1; - - return _uiInstanceId; -} - -/** - * Class UIController - * @param {Object} [options] - options - * @param {jQuery} [options.rootElement] - root element - * @param {string} [options.tagName] - tag name - * @param {string} [options.className] - class name - */ - -var UIController = function () { - - /** - * UI jQuery element - * @type {Object} - */ - - /** - * tag name - * @type {string} - */ - function UIController() { - var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - _classCallCheck(this, UIController); - - options = _tuiCodeSnippet2.default.extend({ - tagName: 'div' - }, options); - - this.tagName = options.tagName; - - this.className = options.className; - - this._id = makeUIInstanceId(); - - this._setRootElement(options.rootElement); - } - - /** - * @param {string|object} aType - event name and selector string - * @param {function} aFn - event handler - */ - - - /** - * UI Id - * @type {number} - * @private - */ - - - /** - * ui controller class name - * @type {string} - */ - - - _createClass(UIController, [{ - key: 'on', - value: function on(aType, aFn) { - var _this = this; - - if (_tuiCodeSnippet2.default.isObject(aType)) { - _tuiCodeSnippet2.default.forEach(aType, function (fn, type) { - _this._addEvent(type, fn); - }); - } else { - this._addEvent(aType, aFn); - } - } - - /** - * bind event - * @param {string} type - event name and selector - * @param {function} fn - handler function - * @private - */ - - }, { - key: '_addEvent', - value: function _addEvent(type, fn) { - var _parseEventType2 = this._parseEventType(type), - event = _parseEventType2.event, - selector = _parseEventType2.selector; - - if (selector) { - this.$el.on(event, selector, fn); - } else { - this.$el.on(event, fn); - } - } - - /** - * unbind event handler - * @param {string} type - event name and selector - * @param {function} fn - handler function - */ - - }, { - key: 'off', - value: function off(type, fn) { - if (type) { - var _parseEventType3 = this._parseEventType(type), - event = _parseEventType3.event, - selector = _parseEventType3.selector; - - if (selector) { - this.$el.off(event, selector, fn); - } else { - this.$el.off(event, fn); - } - } else { - this.$el.off(); - } - } - - /** - * parse string into event name & selector - * 'click td' => ['click', 'td] - * @param {string} type - string to be parsed - * @returns {Object} event, selector - * @private - */ - - }, { - key: '_parseEventType', - value: function _parseEventType(type) { - var splitType = type.split(' '); - var event = splitType.shift(); - var selector = splitType.join(' '); - - return { - event: event, - selector: selector - }; - } - - /** - * set root element - * @param {jQuery} $el - root jQuery element - * @private - */ - - }, { - key: '_setRootElement', - value: function _setRootElement($el) { - var tagName = this.tagName; - var className = this.className; - - - if (!$el) { - className = className || 'uic' + this._id; - $el = (0, _jquery2.default)('<' + tagName + ' class="' + className + '"/>'); - } - this.$el = $el; - } - - /** - * trigger event - * @param {...object} args - event name & extra params - */ - - }, { - key: 'trigger', - value: function trigger() { - var _$el; - - (_$el = this.$el).trigger.apply(_$el, arguments); - } - }, { - key: '_getEventNameWithNamespace', - value: function _getEventNameWithNamespace(event) { - var eventSplited = event.split(' '); - eventSplited[0] += '.uicEvent' + this._id; - - return eventSplited.join(' '); - } - - /** - * remove - */ - - }, { - key: 'remove', - value: function remove() { - if (this.$el) { - this.$el.remove(); - } - } - - /** - * destroy - */ - - }, { - key: 'destroy', - value: function destroy() { - var _this2 = this; - - this.remove(); - - _tuiCodeSnippet2.default.forEachOwnProperties(this, function (value, key) { - _this2[key] = null; - }); - } - }]); - - return UIController; -}(); - -exports.default = UIController; - -/***/ }), -/* 15 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview Implement Module for managing import external data such as image - * @author NHN FE Development Lab - */ - - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var URLRegex = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})(\/([^\s]*))?$/g; - -/** - * Class ImportManager - * @param {EventManager} eventManager - eventManager - * @ignore - */ - -var ImportManager = function () { - function ImportManager(eventManager) { - _classCallCheck(this, ImportManager); - - this.eventManager = eventManager; - - this._initEvent(); - this._initDefaultImageImporter(); - } - - /** - * graceful decode uri component - * @param {string} originalURI - string to be decoded - * @returns {string} decoded string - * @static - */ - - - _createClass(ImportManager, [{ - key: '_initEvent', - - - /** - * Initialize event handler - * @private - */ - value: function _initEvent() { - var _this = this; - - this.eventManager.listen('drop', function (ev) { - var items = ev.data.dataTransfer && ev.data.dataTransfer.files; - _this._processBlobItems(items, ev.data); - }); - - this.eventManager.listen('willPaste', function (ev) { - // IE has no interface to handle clipboard image. #976 - var fragment = ev.data.fragment; - var descendant = fragment.querySelectorAll('*'); - // only if paste event data has one img element and the element has base64 encoded image - if (descendant.length !== 1 || descendant[0].tagName !== 'IMG' || !/^data:image/.test(descendant[0].src)) { - return; - } - ev.data.preventDefault(); - - var blob = dataURItoBlob(descendant[0].src); - _this._emitAddImageBlobHook(blob, 'paste'); - }); - - this.eventManager.listen('paste', function (ev) { - _this._processClipboard(ev.data); - }); - - this.eventManager.listen('pasteBefore', function (ev) { - _this._decodeURL(ev); - }); - } - - /** - * Initialize default image importer - * @private - */ - - }, { - key: '_initDefaultImageImporter', - value: function _initDefaultImageImporter() { - this.eventManager.listen('addImageBlobHook', function (blob, callback) { - var reader = new FileReader(); - - reader.onload = function (event) { - callback(event.target.result); - }; - - reader.readAsDataURL(blob); - }); - } - - /** - * Emit add image blob hook - * @param {object} blob - blob or file - * @param {string} type - type of an event the item belongs to. paste or drop - * @private - */ - - }, { - key: '_emitAddImageBlobHook', - value: function _emitAddImageBlobHook(blob, type) { - var _this2 = this; - - this.eventManager.emit('addImageBlobHook', blob, function (imageUrl, altText) { - _this2.eventManager.emit('command', 'AddImage', { - imageUrl: imageUrl, - altText: altText || blob.name || 'image' - }); - }, type); - } - - /** - * Decode url when paste link - * @param {object} ev - event object - * @private - */ - - }, { - key: '_decodeURL', - value: function _decodeURL(ev) { - var decodeURIGraceful = ImportManager.decodeURIGraceful, - encodeMarkdownCharacters = ImportManager.encodeMarkdownCharacters; - - - if (ev.source === 'markdown' && ev.data.text) { - var texts = ev.data.text; - var text = texts[0]; - if (texts.length === 1 && text.match(URLRegex)) { - text = decodeURIGraceful(text); - text = encodeMarkdownCharacters(text); - ev.data.update(null, null, [text]); - } - } else if (ev.source === 'wysiwyg') { - var container = ev.$clipboardContainer.get(0); - var firstChild = container.childNodes[0]; - var _text = firstChild.innerText; - if (container.childNodes.length === 1 && firstChild.tagName === 'A' && _text.match(URLRegex)) { - firstChild.innerText = decodeURIGraceful(_text); - firstChild.href = encodeMarkdownCharacters(firstChild.href); - } - } - } - - /** - * Get blob or excel data from clipboard - * @param {object} evData Clipboard data - * @private - */ - - }, { - key: '_processClipboard', - value: function _processClipboard(evData) { - var cbData = evData.clipboardData || window.clipboardData; - var blobItems = cbData && cbData.items; - var types = cbData.types; - - - if (blobItems && types && types.length === 1 && _tuiCodeSnippet2.default.inArray('Files', [].slice.call(types)) !== -1) { - this._processBlobItems(blobItems, evData); - } - } - - /** - * Process for blob item - * @param {Array.} items Item array - * @param {object} evData Event data - * @private - */ - - }, { - key: '_processBlobItems', - value: function _processBlobItems(items, evData) { - var _this3 = this; - - if (items) { - _tuiCodeSnippet2.default.forEachArray(items, function (item) { - if (item.type.indexOf('image') !== -1) { - evData.preventDefault(); - evData.stopPropagation(); - evData.codemirrorIgnore = true; - - var blob = item.name ? item : item.getAsFile(); // Blob or File - _this3._emitAddImageBlobHook(blob, evData.type); - - return false; - } - - return true; - }); - } - } - }], [{ - key: 'decodeURIGraceful', - value: function decodeURIGraceful(originalURI) { - var uris = originalURI.split(' '); - var decodedURIs = []; - var decodedURI = void 0; - - _tuiCodeSnippet2.default.forEachArray(uris, function (uri) { - try { - decodedURI = decodeURIComponent(uri); - decodedURI = decodedURI.replace(/ /g, '%20'); - } catch (e) { - decodedURI = uri; - } - - return decodedURIs.push(decodedURI); - }); - - return decodedURIs.join(' '); - } - - /** - * encode markdown critical characters - * @param {string} text - string to encode - * @returns {string} - markdown character encoded string - * @static - */ - - }, { - key: 'encodeMarkdownCharacters', - value: function encodeMarkdownCharacters(text) { - return text.replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\[/g, '%5B').replace(/\]/g, '%5D').replace(//g, '%3E'); - } - - /** - * escape markdown critical characters - * @param {string} text - string to escape - * @returns {string} - markdown character escaped string - * @static - */ - - }, { - key: 'escapeMarkdownCharacters', - value: function escapeMarkdownCharacters(text) { - return text.replace(/\(/g, '\\(').replace(/\)/g, '\\)').replace(/\[/g, '\\[').replace(/\]/g, '\\]').replace(//g, '\\>'); - } - }]); - - return ImportManager; -}(); - -/** - * data URI to Blob - * @param {string} dataURI - data URI string - * @returns {Blob} - blob data - * @ignore - */ - - -function dataURItoBlob(dataURI) { - var byteString = atob(dataURI.split(',')[1]); - var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; - var ab = new ArrayBuffer(byteString.length); - var ia = new Uint8Array(ab); - for (var i = 0; i < byteString.length; i += 1) { - ia[i] = byteString.charCodeAt(i); - } - var blob = new Blob([ab], { type: mimeString }); - - return blob; -} - -exports.default = ImportManager; - -/***/ }), -/* 16 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(Buffer) {// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. - -function isArray(arg) { - if (Array.isArray) { - return Array.isArray(arg); - } - return objectToString(arg) === '[object Array]'; -} -exports.isArray = isArray; - -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; - -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; - -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; - -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; - -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; - -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; - -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; - -function isRegExp(re) { - return objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; - -function isDate(d) { - return objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; - -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; - -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; - -exports.isBuffer = Buffer.isBuffer; - -function objectToString(o) { - return Object.prototype.toString.call(o); -} - -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(51).Buffer)) - -/***/ }), -/* 17 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _uicontroller = __webpack_require__(14); - -var _uicontroller2 = _interopRequireDefault(_uicontroller); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements Toolbar Item - * @author NHN FE Development Lab - */ - - -/** - * Class ToolbarItem - * @param {Object} [options={name: 'toolbar-item'}] [description] - */ -var ToolbarItem = function (_UIController) { - _inherits(ToolbarItem, _UIController); - - /** - * item name - * @type {String} - * @static - * @private - */ - function ToolbarItem() { - var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { - name: ToolbarItem.name - }; - - _classCallCheck(this, ToolbarItem); - - var _this = _possibleConstructorReturn(this, (ToolbarItem.__proto__ || Object.getPrototypeOf(ToolbarItem)).call(this, _tuiCodeSnippet2.default.extend({ - className: ToolbarItem.className - }, options))); - - _this._name = options.name; - return _this; - } - - /** - * get the name of the toolbar item - * @returns {string} - the name of the toolbar item - */ - - - /** - * toolbar item class name - * @type {String} - * @static - * @private - */ - - - _createClass(ToolbarItem, [{ - key: 'getName', - value: function getName() { - return this._name; - } - }]); - - return ToolbarItem; -}(_uicontroller2.default); - -Object.defineProperty(ToolbarItem, 'name', { - enumerable: true, - writable: true, - value: 'item' -}); -Object.defineProperty(ToolbarItem, 'className', { - enumerable: true, - writable: true, - value: 'tui-toolbar-item' -}); -exports.default = ToolbarItem; - -/***/ }), -/* 18 */ -/***/ (function(module, exports) { - -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - -} -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - - - -} -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; - -process.listeners = function (name) { return [] } - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - - -/***/ }), -/* 19 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/* WEBPACK VAR INJECTION */(function(process) { - -if (typeof process === 'undefined' || - !process.version || - process.version.indexOf('v0.') === 0 || - process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) { - module.exports = { nextTick: nextTick }; -} else { - module.exports = process -} - -function nextTick(fn, arg1, arg2, arg3) { - if (typeof fn !== 'function') { - throw new TypeError('"callback" argument must be a function'); - } - var len = arguments.length; - var args, i; - switch (len) { - case 0: - case 1: - return process.nextTick(fn); - case 2: - return process.nextTick(function afterTickOne() { - fn.call(null, arg1); - }); - case 3: - return process.nextTick(function afterTickTwo() { - fn.call(null, arg1, arg2); - }); - case 4: - return process.nextTick(function afterTickThree() { - fn.call(null, arg1, arg2, arg3); - }); - default: - args = new Array(len - 1); - i = 0; - while (i < args.length) { - args[i++] = arguments[i]; - } - return process.nextTick(function afterTick() { - fn.apply(null, args); - }); - } -} - - -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(18))) - -/***/ }), -/* 20 */ -/***/ (function(module, exports, __webpack_require__) { - -/* eslint-disable node/no-deprecated-api */ -var buffer = __webpack_require__(51) -var Buffer = buffer.Buffer - -// alternative to using Object.keys for old browsers -function copyProps (src, dst) { - for (var key in src) { - dst[key] = src[key] - } -} -if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { - module.exports = buffer -} else { - // Copy properties from require('buffer') - copyProps(buffer, exports) - exports.Buffer = SafeBuffer -} - -function SafeBuffer (arg, encodingOrOffset, length) { - return Buffer(arg, encodingOrOffset, length) -} - -// Copy static methods from Buffer -copyProps(Buffer, SafeBuffer) - -SafeBuffer.from = function (arg, encodingOrOffset, length) { - if (typeof arg === 'number') { - throw new TypeError('Argument must not be a number') - } - return Buffer(arg, encodingOrOffset, length) -} - -SafeBuffer.alloc = function (size, fill, encoding) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - var buf = Buffer(size) - if (fill !== undefined) { - if (typeof encoding === 'string') { - buf.fill(fill, encoding) - } else { - buf.fill(fill) - } - } else { - buf.fill(0) - } - return buf -} - -SafeBuffer.allocUnsafe = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - return Buffer(size) -} - -SafeBuffer.allocUnsafeSlow = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - return buffer.SlowBuffer(size) -} - - -/***/ }), -/* 21 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _toolbarItem = __webpack_require__(17); - -var _toolbarItem2 = _interopRequireDefault(_toolbarItem); - -var _tooltip = __webpack_require__(31); - -var _tooltip2 = _interopRequireDefault(_tooltip); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements UI Button - * @author NHN FE Development Lab - */ - - -/** - * Class Button UI - * @param {object} options - button options - * @param {string} options.className - button class name - * @param {string} options.command - command name to execute on click - * @param {string} options.event - event name to trigger on click - * @param {string} options.text - text on button - * @param {string} options.tooltip - text on tooltip - * @param {string} options.style - button style - * @param {string} options.state - button state - * @param {jquery} $el - button rootElement - * @deprecated - */ -var Button = function (_ToolbarItem) { - _inherits(Button, _ToolbarItem); - - /** - * item name - * @type {String} - * @static - */ - function Button() { - var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { - tagName: 'button', - name: Button.name - }; - - _classCallCheck(this, Button); - - var _this = _possibleConstructorReturn(this, (Button.__proto__ || Object.getPrototypeOf(Button)).call(this, { - name: options.name, - tagName: 'button', - className: options.className + ' ' + Button.className, - rootElement: options.$el - })); - - _this._setOptions(options); - - _this._render(); - _this.on('click', _this._onClick.bind(_this)); - if (options.tooltip) { - _this.on('mouseover', _this._onOver.bind(_this)); - _this.on('mouseout', _this._onOut.bind(_this)); - } - return _this; - } - - /** - * set tooltip text - * @param {string} text - tooltip text to show - */ - - - /** - * ToolbarItem className - * @type {String} - * @static - */ - - - _createClass(Button, [{ - key: 'setTooltip', - value: function setTooltip(text) { - this._tooltip = text; - } - }, { - key: '_setOptions', - value: function _setOptions(options) { - this._command = options.command; - this._event = options.event; - this._text = options.text; - this._tooltip = options.tooltip; - this._style = options.style; - this._state = options.state; - } - }, { - key: '_render', - value: function _render() { - this.$el.text(this._text); - this.$el.attr('type', 'button'); - - if (this._style) { - this.$el.attr('style', this._style); - } - } - }, { - key: '_onClick', - value: function _onClick() { - if (!this.isEnabled()) { - return; - } - - if (this._command) { - this.trigger('command', this._command); - } else if (this._event) { - this.trigger('event', this._event); - } - - this.trigger('clicked'); - } - }, { - key: '_onOver', - value: function _onOver() { - if (!this.isEnabled()) { - return; - } - - _tooltip2.default.show(this.$el, this._tooltip); - } - }, { - key: '_onOut', - value: function _onOut() { - _tooltip2.default.hide(); - } - - /** - * enable button - */ - - }, { - key: 'enable', - value: function enable() { - this.$el.attr('disabled', false); - } - - /** - * disable button - */ - - }, { - key: 'disable', - value: function disable() { - this.$el.attr('disabled', true); - } - - /** - * check whether this button is enabled - * @returns {Boolean} - true for enabled - */ - - }, { - key: 'isEnabled', - value: function isEnabled() { - return !this.$el.attr('disabled'); - } - }]); - - return Button; -}(_toolbarItem2.default); - -Object.defineProperty(Button, 'name', { - enumerable: true, - writable: true, - value: 'button' -}); -Object.defineProperty(Button, 'className', { - enumerable: true, - writable: true, - value: 'tui-toolbar-icons' -}); -exports.default = Button; - -/***/ }), -/* 22 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * @fileoverview Implements KeyMapper - * @author NHN FE Development Lab - */ - -/** - * Constant of key mapping - * @type {string[]} - * @ignore - */ -var KEYBOARD_MAP = ['', // [0] -'', // [1] -'', // [2] -'CANCEL', // [3] -'', // [4] -'', // [5] -'HELP', // [6] -'', // [7] -'BACK_SPACE', // [8] -'TAB', // [9] -'', // [10] -'', // [11] -'CLEAR', // [12] -'ENTER', // [13] -'ENTER_SPECIAL', // [14] -'', // [15] -'', // [16] SHIFT -'', // [17] CONTROL -'', // [18] ALT -'PAUSE', // [19] -'CAPS_LOCK', // [20] -'KANA', // [21] -'EISU', // [22] -'JUNJA', // [23] -'FINAL', // [24] -'HANJA', // [25] -'', // [26] -'ESCAPE', // [27] -'CONVERT', // [28] -'NONCONVERT', // [29] -'ACCEPT', // [30] -'MODECHANGE', // [31] -'SPACE', // [32] -'PAGE_UP', // [33] -'PAGE_DOWN', // [34] -'END', // [35] -'HOME', // [36] -'LEFT', // [37] -'UP', // [38] -'RIGHT', // [39] -'DOWN', // [40] -'SELECT', // [41] -'PRINT', // [42] -'EXECUTE', // [43] -'PRINTSCREEN', // [44] -'INSERT', // [45] -'DELETE', // [46] -'', // [47] -'0', // [48] -'1', // [49] -'2', // [50] -'3', // [51] -'4', // [52] -'5', // [53] -'6', // [54] -'7', // [55] -'8', // [56] -'9', // [57] -':', // [58] -';', // [59] -'<', // [60] -'=', // [61] -'>', // [62] -'?', // [63] -'AT', // [64] -'A', // [65] -'B', // [66] -'C', // [67] -'D', // [68] -'E', // [69] -'F', // [70] -'G', // [71] -'H', // [72] -'I', // [73] -'J', // [74] -'K', // [75] -'L', // [76] -'M', // [77] -'N', // [78] -'O', // [79] -'P', // [80] -'Q', // [81] -'R', // [82] -'S', // [83] -'T', // [84] -'U', // [85] -'V', // [86] -'W', // [87] -'X', // [88] -'Y', // [89] -'Z', // [90] -'', // [91] META -'', // [92] -'CONTEXT_MENU', // [93] -'', // [94] -'SLEEP', // [95] -'NUMPAD0', // [96] -'NUMPAD1', // [97] -'NUMPAD2', // [98] -'NUMPAD3', // [99] -'NUMPAD4', // [100] -'NUMPAD5', // [101] -'NUMPAD6', // [102] -'NUMPAD7', // [103] -'NUMPAD8', // [104] -'NUMPAD9', // [105] -'MULTIPLY', // [106] -'ADD', // [107] -'SEPARATOR', // [108] -'SUBTRACT', // [109] -'DECIMAL', // [110] -'DIVIDE', // [111] -'F1', // [112] -'F2', // [113] -'F3', // [114] -'F4', // [115] -'F5', // [116] -'F6', // [117] -'F7', // [118] -'F8', // [119] -'F9', // [120] -'F10', // [121] -'F11', // [122] -'F12', // [123] -'F13', // [124] -'F14', // [125] -'F15', // [126] -'F16', // [127] -'F17', // [128] -'F18', // [129] -'F19', // [130] -'F20', // [131] -'F21', // [132] -'F22', // [133] -'F23', // [134] -'F24', // [135] -'', // [136] -'', // [137] -'', // [138] -'', // [139] -'', // [140] -'', // [141] -'', // [142] -'', // [143] -'NUM_LOCK', // [144] -'SCROLL_LOCK', // [145] -'WIN_OEM_FJ_JISHO', // [146] -'WIN_OEM_FJ_MASSHOU', // [147] -'WIN_OEM_FJ_TOUROKU', // [148] -'WIN_OEM_FJ_LOYA', // [149] -'WIN_OEM_FJ_ROYA', // [150] -'', // [151] -'', // [152] -'', // [153] -'', // [154] -'', // [155] -'', // [156] -'', // [157] -'', // [158] -'', // [159] -'@', // [160] -'!', // [161] -'"', // [162] -'#', // [163] -'$', // [164] -'%', // [165] -'&', // [166] -'_', // [167] -'(', // [168] -')', // [169] -'*', // [170] -'+', // [171] -'|', // [172] -'-', // [173] -'{', // [174] -'}', // [175] -'~', // [176] -'', // [177] -'', // [178] -'', // [179] -'', // [180] -'VOLUME_MUTE', // [181] -'VOLUME_DOWN', // [182] -'VOLUME_UP', // [183] -'', // [184] -'', // [185] -';', // [186] -'=', // [187] -',', // [188] -'-', // [189] -'.', // [190] -'/', // [191] -'`', // [192] -'', // [193] -'', // [194] -'', // [195] -'', // [196] -'', // [197] -'', // [198] -'', // [199] -'', // [200] -'', // [201] -'', // [202] -'', // [203] -'', // [204] -'', // [205] -'', // [206] -'', // [207] -'', // [208] -'', // [209] -'', // [210] -'', // [211] -'', // [212] -'', // [213] -'', // [214] -'', // [215] -'', // [216] -'', // [217] -'', // [218] -'[', // [219] -'\\', // [220] -']', // [221] -'\'', // [222] -'', // [223] -'META', // [224] -'ALTGR', // [225] -'', // [226] -'WIN_ICO_HELP', // [227] -'WIN_ICO_00', // [228] -'', // [229] -'WIN_ICO_CLEAR', // [230] -'', // [231] -'', // [232] -'WIN_OEM_RESET', // [233] -'WIN_OEM_JUMP', // [234] -'WIN_OEM_PA1', // [235] -'WIN_OEM_PA2', // [236] -'WIN_OEM_PA3', // [237] -'WIN_OEM_WSCTRL', // [238] -'WIN_OEM_CUSEL', // [239] -'WIN_OEM_ATTN', // [240] -'WIN_OEM_FINISH', // [241] -'WIN_OEM_COPY', // [242] -'WIN_OEM_AUTO', // [243] -'WIN_OEM_ENLW', // [244] -'WIN_OEM_BACKTAB', // [245] -'ATTN', // [246] -'CRSEL', // [247] -'EXSEL', // [248] -'EREOF', // [249] -'PLAY', // [250] -'ZOOM', // [251] -'', // [252] -'PA1', // [253] -'WIN_OEM_CLEAR', // [254] -'' // [255] -]; - -var sharedInstance = void 0; - -/** - * Class KeyMapper - * @param {object} [options] options - * @param {string} options.splitter splitter string default is + - * @ignore - */ - -var KeyMapper = function () { - function KeyMapper(options) { - _classCallCheck(this, KeyMapper); - - this._setSplitter(options); - } - - /** - * Set key splitter - * @param {object} options Option object - * @private - */ - - - _createClass(KeyMapper, [{ - key: '_setSplitter', - value: function _setSplitter(options) { - var splitter = options ? options.splitter : '+'; - this._splitter = splitter; - } - - /** - * Convert event to keyMap - * @param {event} event Event object - * @returns {string} - */ - - }, { - key: 'convert', - value: function convert(event) { - var keyMap = []; - - if (event.shiftKey) { - keyMap.push('SHIFT'); - } - - if (event.ctrlKey) { - keyMap.push('CTRL'); - } - - if (event.metaKey) { - keyMap.push('META'); - } - - if (event.altKey) { - keyMap.push('ALT'); - } - - var keyChar = this._getKeyCodeChar(event.keyCode); - - if (keyChar) { - keyMap.push(keyChar); - } - - return keyMap.join(this._splitter); - } - - /** - * Get character from key code - * @param {number} keyCode Key code - * @returns {string} - * @private - */ - - }, { - key: '_getKeyCodeChar', - value: function _getKeyCodeChar(keyCode) { - var keyCodeCharacter = KEYBOARD_MAP[keyCode]; - - return keyCodeCharacter; - } - - /** - * Get sharedInstance - * @returns {KeyMapper} - */ - - }], [{ - key: 'getSharedInstance', - value: function getSharedInstance() { - if (!sharedInstance) { - sharedInstance = new KeyMapper(); - } - - return sharedInstance; - } - - /** - * get key code for a character - * @param {string} char - a character to be converted - * @returns {number} key code for the char - * @static - */ - - }, { - key: 'keyCode', - value: function keyCode(char) { - return KEYBOARD_MAP.indexOf(char); - } - }]); - - return KeyMapper; -}(); - -exports.default = KeyMapper; - -/***/ }), -/* 23 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview Implements htmlSanitizer - * @author NHN FE Development Lab - */ -var HTML_ATTR_LIST_RX = new RegExp('^(abbr|align|alt|axis|bgcolor|border|cellpadding|cellspacing|class|clear|' + 'color|cols|compact|coords|dir|face|headers|height|hreflang|hspace|' + 'ismap|lang|language|nohref|nowrap|rel|rev|rows|rules|' + 'scope|scrolling|shape|size|span|start|summary|tabindex|target|title|type|' + 'valign|value|vspace|width|checked|mathvariant|encoding|id|name|' + 'background|cite|href|longdesc|src|usemap|xlink:href|data-+|checked|style)', 'g'); - -var SVG_ATTR_LIST_RX = new RegExp('^(accent-height|accumulate|additive|alphabetic|arabic-form|ascent|' + 'baseProfile|bbox|begin|by|calcMode|cap-height|class|color|color-rendering|content|' + 'cx|cy|d|dx|dy|descent|display|dur|end|fill|fill-rule|font-family|font-size|font-stretch|' + 'font-style|font-variant|font-weight|from|fx|fy|g1|g2|glyph-name|gradientUnits|hanging|' + 'height|horiz-adv-x|horiz-origin-x|ideographic|k|keyPoints|keySplines|keyTimes|lang|' + 'marker-end|marker-mid|marker-start|markerHeight|markerUnits|markerWidth|mathematical|' + 'max|min|offset|opacity|orient|origin|overline-position|overline-thickness|panose-1|' + 'path|pathLength|points|preserveAspectRatio|r|refX|refY|repeatCount|repeatDur|' + 'requiredExtensions|requiredFeatures|restart|rotate|rx|ry|slope|stemh|stemv|stop-color|' + 'stop-opacity|strikethrough-position|strikethrough-thickness|stroke|stroke-dasharray|' + 'stroke-dashoffset|stroke-linecap|stroke-linejoin|stroke-miterlimit|stroke-opacity|' + 'stroke-width|systemLanguage|target|text-anchor|to|transform|type|u1|u2|underline-position|' + 'underline-thickness|unicode|unicode-range|units-per-em|values|version|viewBox|visibility|' + 'width|widths|x|x-height|x1|x2|xlink:actuate|xlink:arcrole|xlink:role|xlink:show|xlink:title|' + 'xlink:type|xml:base|xml:lang|xml:space|xmlns|xmlns:xlink|y|y1|y2|zoomAndPan)', 'g'); - -var ATTR_VALUE_BLACK_LIST_RX = { - 'href': /^(javascript:).*/g -}; - -/** - * htmlSanitizer - * @param {string|Node} html html or Node - * @param {boolean} [needHtmlText] pass true if need html text - * @returns {string|DocumentFragment} result - * @ignore - */ -function htmlSanitizer(html, needHtmlText) { - var $html = (0, _jquery2.default)('
    '); - - html = html.replace(//g, ''); - - $html.append(html); - - removeUnnecessaryTags($html); - leaveOnlyWhitelistAttribute($html); - removeInvalidAttributeValues($html); - - return finalizeHtml($html, needHtmlText); -} - -/** - * Remove unnecessary tags - * @private - * @param {jQuery} $html jQuery instance - */ -function removeUnnecessaryTags($html) { - $html.find('script, iframe, textarea, form, button, select, meta, style, link, title, embed, object, details, summary').remove(); -} - -/** - * Leave only white list attributes - * @private - * @param {jQuery} $html jQuery instance - */ -function leaveOnlyWhitelistAttribute($html) { - $html.find('*').each(function (index, node) { - var attrs = node.attributes; - var blacklist = _tuiCodeSnippet2.default.toArray(attrs).filter(function (attr) { - var isHTMLAttr = attr.name.match(HTML_ATTR_LIST_RX); - var isSVGAttr = attr.name.match(SVG_ATTR_LIST_RX); - - return !isHTMLAttr && !isSVGAttr; - }); - - _tuiCodeSnippet2.default.forEachArray(blacklist, function (attr) { - // Edge svg attribute name returns uppercase bug. error guard. - // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/5579311/ - if (attrs.getNamedItem(attr.name)) { - attrs.removeNamedItem(attr.name); - } - }); - }); -} - -/** - * Remove invalid attribute values - * @private - * @param {jQuery} $html jQuery instance - */ -function removeInvalidAttributeValues($html) { - var _loop = function _loop(attr) { - if (ATTR_VALUE_BLACK_LIST_RX.hasOwnProperty(attr)) { - $html.find('[' + attr + ']').each(function (index, node) { - var attrs = node.attributes; - var valueBlackListRX = ATTR_VALUE_BLACK_LIST_RX[attr]; - var attrItem = attrs.getNamedItem(attr); - if (valueBlackListRX && attrItem && attrItem.value.toLowerCase().match(valueBlackListRX)) { - attrs.removeNamedItem(attr); - } - }); - } - }; - - for (var attr in ATTR_VALUE_BLACK_LIST_RX) { - _loop(attr); - } -} - -/** - * Finalize html result - * @private - * @param {jQuery} $html jQuery instance - * @param {boolean} needHtmlText pass true if need html text - * @returns {string|DocumentFragment} result - */ -function finalizeHtml($html, needHtmlText) { - var returnValue = void 0; - - if (needHtmlText) { - returnValue = $html[0].innerHTML; - } else { - var frag = document.createDocumentFragment(); - var childNodes = _tuiCodeSnippet2.default.toArray($html[0].childNodes); - var length = childNodes.length; - - - for (var i = 0; i < length; i += 1) { - frag.appendChild(childNodes[i]); - } - returnValue = frag; - } - - return returnValue; -} - -exports.default = htmlSanitizer; - -/***/ }), -/* 24 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE__24__; - -/***/ }), -/* 25 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.CodeBlockManager = undefined; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview Implements CodeBlockManager - * @author NHN FE Development Lab - */ - - -var _highlight = __webpack_require__(94); - -var _highlight2 = _interopRequireDefault(_highlight); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Class Code Block Manager - */ -var CodeBlockManager = function () { - function CodeBlockManager() { - _classCallCheck(this, CodeBlockManager); - - this._replacers = {}; - } - - /** - * Set replacer for code block - * @param {string} language - code block language - * @param {function} replacer - replacer function to code block element - */ - - - _createClass(CodeBlockManager, [{ - key: 'setReplacer', - value: function setReplacer(language, replacer) { - this._replacers[language] = replacer; - } - - /** - * get replacer for code block - * @param {string} language - code block type - * @returns {function} - replacer function - */ - - }, { - key: 'getReplacer', - value: function getReplacer(language) { - return this._replacers[language]; - } - - /** - * Create code block html. - * @param {string} language - code block language - * @param {string} codeText - code text - * @returns {string} - */ - - }, { - key: 'createCodeBlockHtml', - value: function createCodeBlockHtml(language, codeText) { - var replacer = this.getReplacer(language); - var html = void 0; - - if (replacer) { - html = replacer(codeText, language); - } else { - html = _highlight2.default.getLanguage(language) ? _highlight2.default.highlight(language, codeText).value : escape(codeText, false); - } - - return html; - } - - /** - * get supported languages by highlight-js - * @returns {Array} - supported languages by highlight-js - */ - - }], [{ - key: 'getHighlightJSLanguages', - value: function getHighlightJSLanguages() { - return _highlight2.default.listLanguages(); - } - }]); - - return CodeBlockManager; -}(); - -/** - * escape code from markdown-it - * @param {string} html HTML string - * @param {string} encode Boolean value of whether encode or not - * @returns {string} - * @ignore - */ - - -function escape(html, encode) { - return html.replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, '''); -} - -exports.CodeBlockManager = CodeBlockManager; -exports.default = new CodeBlockManager(); - -/***/ }), -/* 26 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -/** - * @fileoverview This file is common logic for italic, bold, strike makrdown commands. - * @author NHN FE Development Lab - */ - -/** - * range expand according to expendSize - * If can not expand, return null - * @param {range} range - range - * @param {number} expendSize - expendSize - * @returns {object} expanded range or null - * @ignore - */ -var getExpandedRange = function getExpandedRange(range, expendSize) { - var start = range.start, - end = range.end; - - var expendRange = void 0; - - if (start.ch >= expendSize) { - var from = { - line: start.line, - ch: start.ch - expendSize - }; - var to = { - line: end.line, - ch: end.ch + expendSize - }; - - expendRange = { - from: from, - to: to - }; - } - - return expendRange; -}; - -/** - * remove symbol in the front and back of text - * @param {string} text - text - * @param {string} symbol - text - * @returns {string} - * @ignore - */ -var removeSyntax = exports.removeSyntax = function removeSyntax(text, symbol) { - var symbolLength = symbol.length; - - return text.substr(symbolLength, text.length - symbolLength * 2); -}; - -/** - * append symbol in the front and back of text - * @param {string} text - text - * @param {string} symbol - text - * @returns {string} - * @ignore - */ -var appendSyntax = exports.appendSyntax = function appendSyntax(text, symbol) { - return '' + symbol + text + symbol; -}; - -/** - * check expanded text and replace text using replacer - * @param {CodeMirror.doc} doc - doc of codemirror - * @param {range} range - origin range - * @param {number} expandSize - expandSize - * @param {function} checker - sytax check function - * @param {function} replacer - text replace function - * @returns {boolean} - if replace text, return true. - * @ignore - */ -var expandReplace = exports.expandReplace = function expandReplace(doc, range, expandSize, checker, replacer) { - var expendRange = getExpandedRange(range, expandSize); - var result = false; - - if (expendRange) { - var from = expendRange.from, - to = expendRange.to; - - var expendRangeText = doc.getRange(from, to); - if (checker(expendRangeText)) { - doc.setSelection(from, to); - doc.replaceSelection(replacer(expendRangeText), 'around'); - result = true; - } - } - - return result; -}; - -/** - * check text and replace text using replacer - * @param {CodeMirror.doc} doc - doc of codemirror - * @param {string} text - text - * @param {function} checker - sytax check function - * @param {function} replacer - text replace function - * @returns {boolean} - if replace text, return true. - * @ignore - */ -var replace = exports.replace = function replace(doc, text, checker, replacer) { - var result = false; - - if (checker(text)) { - doc.replaceSelection(replacer(text), 'around'); - result = true; - } - - return result; -}; - -var changeSyntax = exports.changeSyntax = function changeSyntax(doc, range, symbol, syntaxRegex, contentRegex) { - var _doc$getCursor = doc.getCursor(), - line = _doc$getCursor.line, - ch = _doc$getCursor.ch; - - var selectionStr = doc.getSelection(); - var symbolLength = symbol.length; - var isSyntax = function isSyntax(t) { - return syntaxRegex.test(t); - }; - - // 1. expand text and check syntax => remove syntax - // 2. check text is syntax => remove syntax - // 3. If text does not match syntax, remove syntax inside text and then append syntax - if (!(expandReplace(doc, range, symbolLength, isSyntax, function (t) { - return removeSyntax(t, symbol); - }) || replace(doc, selectionStr, isSyntax, function (t) { - return removeSyntax(t, symbol); - }))) { - var removeSyntaxInsideText = selectionStr.replace(contentRegex, '$1'); - doc.replaceSelection(appendSyntax(removeSyntaxInsideText, symbol), 'around'); - } - - var afterSelectStr = doc.getSelection(); - var size = ch; - - if (!selectionStr) { - // If text was not selected, after replace text, move cursor - // For example **|** => | (move cusor -symbolLenth) - if (isSyntax(afterSelectStr)) { - size += symbolLength; - } else { - size -= symbolLength; - } - doc.setCursor(line, size); - } -}; - -/***/ }), -/* 27 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -var R = typeof Reflect === 'object' ? Reflect : null -var ReflectApply = R && typeof R.apply === 'function' - ? R.apply - : function ReflectApply(target, receiver, args) { - return Function.prototype.apply.call(target, receiver, args); - } - -var ReflectOwnKeys -if (R && typeof R.ownKeys === 'function') { - ReflectOwnKeys = R.ownKeys -} else if (Object.getOwnPropertySymbols) { - ReflectOwnKeys = function ReflectOwnKeys(target) { - return Object.getOwnPropertyNames(target) - .concat(Object.getOwnPropertySymbols(target)); - }; -} else { - ReflectOwnKeys = function ReflectOwnKeys(target) { - return Object.getOwnPropertyNames(target); - }; -} - -function ProcessEmitWarning(warning) { - if (console && console.warn) console.warn(warning); -} - -var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { - return value !== value; -} - -function EventEmitter() { - EventEmitter.init.call(this); -} -module.exports = EventEmitter; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._eventsCount = 0; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -var defaultMaxListeners = 10; - -Object.defineProperty(EventEmitter, 'defaultMaxListeners', { - enumerable: true, - get: function() { - return defaultMaxListeners; - }, - set: function(arg) { - if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { - throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); - } - defaultMaxListeners = arg; - } -}); - -EventEmitter.init = function() { - - if (this._events === undefined || - this._events === Object.getPrototypeOf(this)._events) { - this._events = Object.create(null); - this._eventsCount = 0; - } - - this._maxListeners = this._maxListeners || undefined; -}; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { - if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { - throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); - } - this._maxListeners = n; - return this; -}; - -function $getMaxListeners(that) { - if (that._maxListeners === undefined) - return EventEmitter.defaultMaxListeners; - return that._maxListeners; -} - -EventEmitter.prototype.getMaxListeners = function getMaxListeners() { - return $getMaxListeners(this); -}; - -EventEmitter.prototype.emit = function emit(type) { - var args = []; - for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); - var doError = (type === 'error'); - - var events = this._events; - if (events !== undefined) - doError = (doError && events.error === undefined); - else if (!doError) - return false; - - // If there is no 'error' event listener then throw. - if (doError) { - var er; - if (args.length > 0) - er = args[0]; - if (er instanceof Error) { - // Note: The comments on the `throw` lines are intentional, they show - // up in Node's output if this results in an unhandled exception. - throw er; // Unhandled 'error' event - } - // At least give some kind of context to the user - var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); - err.context = er; - throw err; // Unhandled 'error' event - } - - var handler = events[type]; - - if (handler === undefined) - return false; - - if (typeof handler === 'function') { - ReflectApply(handler, this, args); - } else { - var len = handler.length; - var listeners = arrayClone(handler, len); - for (var i = 0; i < len; ++i) - ReflectApply(listeners[i], this, args); - } - - return true; -}; - -function _addListener(target, type, listener, prepend) { - var m; - var events; - var existing; - - if (typeof listener !== 'function') { - throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); - } - - events = target._events; - if (events === undefined) { - events = target._events = Object.create(null); - target._eventsCount = 0; - } else { - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (events.newListener !== undefined) { - target.emit('newListener', type, - listener.listener ? listener.listener : listener); - - // Re-assign `events` because a newListener handler could have caused the - // this._events to be assigned to a new object - events = target._events; - } - existing = events[type]; - } - - if (existing === undefined) { - // Optimize the case of one listener. Don't need the extra array object. - existing = events[type] = listener; - ++target._eventsCount; - } else { - if (typeof existing === 'function') { - // Adding the second element, need to change to array. - existing = events[type] = - prepend ? [listener, existing] : [existing, listener]; - // If we've already got an array, just append. - } else if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - - // Check for listener leak - m = $getMaxListeners(target); - if (m > 0 && existing.length > m && !existing.warned) { - existing.warned = true; - // No error code for this since it is a Warning - // eslint-disable-next-line no-restricted-syntax - var w = new Error('Possible EventEmitter memory leak detected. ' + - existing.length + ' ' + String(type) + ' listeners ' + - 'added. Use emitter.setMaxListeners() to ' + - 'increase limit'); - w.name = 'MaxListenersExceededWarning'; - w.emitter = target; - w.type = type; - w.count = existing.length; - ProcessEmitWarning(w); - } - } - - return target; -} - -EventEmitter.prototype.addListener = function addListener(type, listener) { - return _addListener(this, type, listener, false); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.prependListener = - function prependListener(type, listener) { - return _addListener(this, type, listener, true); - }; - -function onceWrapper() { - var args = []; - for (var i = 0; i < arguments.length; i++) args.push(arguments[i]); - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - ReflectApply(this.listener, this.target, args); - } -} - -function _onceWrap(target, type, listener) { - var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; - var wrapped = onceWrapper.bind(state); - wrapped.listener = listener; - state.wrapFn = wrapped; - return wrapped; -} - -EventEmitter.prototype.once = function once(type, listener) { - if (typeof listener !== 'function') { - throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); - } - this.on(type, _onceWrap(this, type, listener)); - return this; -}; - -EventEmitter.prototype.prependOnceListener = - function prependOnceListener(type, listener) { - if (typeof listener !== 'function') { - throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); - } - this.prependListener(type, _onceWrap(this, type, listener)); - return this; - }; - -// Emits a 'removeListener' event if and only if the listener was removed. -EventEmitter.prototype.removeListener = - function removeListener(type, listener) { - var list, events, position, i, originalListener; - - if (typeof listener !== 'function') { - throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); - } - - events = this._events; - if (events === undefined) - return this; - - list = events[type]; - if (list === undefined) - return this; - - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) - this._events = Object.create(null); - else { - delete events[type]; - if (events.removeListener) - this.emit('removeListener', type, list.listener || listener); - } - } else if (typeof list !== 'function') { - position = -1; - - for (i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - originalListener = list[i].listener; - position = i; - break; - } - } - - if (position < 0) - return this; - - if (position === 0) - list.shift(); - else { - spliceOne(list, position); - } - - if (list.length === 1) - events[type] = list[0]; - - if (events.removeListener !== undefined) - this.emit('removeListener', type, originalListener || listener); - } - - return this; - }; - -EventEmitter.prototype.off = EventEmitter.prototype.removeListener; - -EventEmitter.prototype.removeAllListeners = - function removeAllListeners(type) { - var listeners, events, i; - - events = this._events; - if (events === undefined) - return this; - - // not listening for removeListener, no need to emit - if (events.removeListener === undefined) { - if (arguments.length === 0) { - this._events = Object.create(null); - this._eventsCount = 0; - } else if (events[type] !== undefined) { - if (--this._eventsCount === 0) - this._events = Object.create(null); - else - delete events[type]; - } - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - var keys = Object.keys(events); - var key; - for (i = 0; i < keys.length; ++i) { - key = keys[i]; - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = Object.create(null); - this._eventsCount = 0; - return this; - } - - listeners = events[type]; - - if (typeof listeners === 'function') { - this.removeListener(type, listeners); - } else if (listeners !== undefined) { - // LIFO order - for (i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } - } - - return this; - }; - -function _listeners(target, type, unwrap) { - var events = target._events; - - if (events === undefined) - return []; - - var evlistener = events[type]; - if (evlistener === undefined) - return []; - - if (typeof evlistener === 'function') - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - - return unwrap ? - unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); -} - -EventEmitter.prototype.listeners = function listeners(type) { - return _listeners(this, type, true); -}; - -EventEmitter.prototype.rawListeners = function rawListeners(type) { - return _listeners(this, type, false); -}; - -EventEmitter.listenerCount = function(emitter, type) { - if (typeof emitter.listenerCount === 'function') { - return emitter.listenerCount(type); - } else { - return listenerCount.call(emitter, type); - } -}; - -EventEmitter.prototype.listenerCount = listenerCount; -function listenerCount(type) { - var events = this._events; - - if (events !== undefined) { - var evlistener = events[type]; - - if (typeof evlistener === 'function') { - return 1; - } else if (evlistener !== undefined) { - return evlistener.length; - } - } - - return 0; -} - -EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; -}; - -function arrayClone(arr, n) { - var copy = new Array(n); - for (var i = 0; i < n; ++i) - copy[i] = arr[i]; - return copy; -} - -function spliceOne(list, index) { - for (; index + 1 < list.length; index++) - list[index] = list[index + 1]; - list.pop(); -} - -function unwrapListeners(arr) { - var ret = new Array(arr.length); - for (var i = 0; i < ret.length; ++i) { - ret[i] = arr[i].listener || arr[i]; - } - return ret; -} - - -/***/ }), -/* 28 */ -/***/ (function(module, exports, __webpack_require__) { - -exports = module.exports = __webpack_require__(48); -exports.Stream = exports; -exports.Readable = exports; -exports.Writable = __webpack_require__(29); -exports.Duplex = __webpack_require__(12); -exports.Transform = __webpack_require__(54); -exports.PassThrough = __webpack_require__(182); - - -/***/ }), -/* 29 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/* WEBPACK VAR INJECTION */(function(process, setImmediate, global) {// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// A bit simpler than readable streams. -// Implement an async ._write(chunk, encoding, cb), and it'll handle all -// the drain event emission and buffering. - - - -/**/ - -var pna = __webpack_require__(19); -/**/ - -module.exports = Writable; - -/* */ -function WriteReq(chunk, encoding, cb) { - this.chunk = chunk; - this.encoding = encoding; - this.callback = cb; - this.next = null; -} - -// It seems a linked list but it is not -// there will be only 2 of these for each stream -function CorkedRequest(state) { - var _this = this; - - this.next = null; - this.entry = null; - this.finish = function () { - onCorkedFinish(_this, state); - }; -} -/* */ - -/**/ -var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick; -/**/ - -/**/ -var Duplex; -/**/ - -Writable.WritableState = WritableState; - -/**/ -var util = __webpack_require__(16); -util.inherits = __webpack_require__(13); -/**/ - -/**/ -var internalUtil = { - deprecate: __webpack_require__(181) -}; -/**/ - -/**/ -var Stream = __webpack_require__(50); -/**/ - -/**/ - -var Buffer = __webpack_require__(20).Buffer; -var OurUint8Array = global.Uint8Array || function () {}; -function _uint8ArrayToBuffer(chunk) { - return Buffer.from(chunk); -} -function _isUint8Array(obj) { - return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; -} - -/**/ - -var destroyImpl = __webpack_require__(52); - -util.inherits(Writable, Stream); - -function nop() {} - -function WritableState(options, stream) { - Duplex = Duplex || __webpack_require__(12); - - options = options || {}; - - // Duplex streams are both readable and writable, but share - // the same options object. - // However, some cases require setting options to different - // values for the readable and the writable sides of the duplex stream. - // These options can be provided separately as readableXXX and writableXXX. - var isDuplex = stream instanceof Duplex; - - // object stream flag to indicate whether or not this stream - // contains buffers or objects. - this.objectMode = !!options.objectMode; - - if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; - - // the point at which write() starts returning false - // Note: 0 is a valid value, means that we always return false if - // the entire buffer is not flushed immediately on write() - var hwm = options.highWaterMark; - var writableHwm = options.writableHighWaterMark; - var defaultHwm = this.objectMode ? 16 : 16 * 1024; - - if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm; - - // cast to ints. - this.highWaterMark = Math.floor(this.highWaterMark); - - // if _final has been called - this.finalCalled = false; - - // drain event flag. - this.needDrain = false; - // at the start of calling end() - this.ending = false; - // when end() has been called, and returned - this.ended = false; - // when 'finish' is emitted - this.finished = false; - - // has it been destroyed - this.destroyed = false; - - // should we decode strings into buffers before passing to _write? - // this is here so that some node-core streams can optimize string - // handling at a lower level. - var noDecode = options.decodeStrings === false; - this.decodeStrings = !noDecode; - - // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - this.defaultEncoding = options.defaultEncoding || 'utf8'; - - // not an actual buffer we keep track of, but a measurement - // of how much we're waiting to get pushed to some underlying - // socket or file. - this.length = 0; - - // a flag to see when we're in the middle of a write. - this.writing = false; - - // when true all writes will be buffered until .uncork() call - this.corked = 0; - - // a flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, because any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. - this.sync = true; - - // a flag to know if we're processing previously buffered items, which - // may call the _write() callback in the same tick, so that we don't - // end up in an overlapped onwrite situation. - this.bufferProcessing = false; - - // the callback that's passed to _write(chunk,cb) - this.onwrite = function (er) { - onwrite(stream, er); - }; - - // the callback that the user supplies to write(chunk,encoding,cb) - this.writecb = null; - - // the amount that is being written when _write is called. - this.writelen = 0; - - this.bufferedRequest = null; - this.lastBufferedRequest = null; - - // number of pending user-supplied write callbacks - // this must be 0 before 'finish' can be emitted - this.pendingcb = 0; - - // emit prefinish if the only thing we're waiting for is _write cbs - // This is relevant for synchronous Transform streams - this.prefinished = false; - - // True if the error was already emitted and should not be thrown again - this.errorEmitted = false; - - // count buffered requests - this.bufferedRequestCount = 0; - - // allocate the first CorkedRequest, there is always - // one allocated and free to use, and we maintain at most two - this.corkedRequestsFree = new CorkedRequest(this); -} - -WritableState.prototype.getBuffer = function getBuffer() { - var current = this.bufferedRequest; - var out = []; - while (current) { - out.push(current); - current = current.next; - } - return out; -}; - -(function () { - try { - Object.defineProperty(WritableState.prototype, 'buffer', { - get: internalUtil.deprecate(function () { - return this.getBuffer(); - }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') - }); - } catch (_) {} -})(); - -// Test _writableState for inheritance to account for Duplex streams, -// whose prototype chain only points to Readable. -var realHasInstance; -if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { - realHasInstance = Function.prototype[Symbol.hasInstance]; - Object.defineProperty(Writable, Symbol.hasInstance, { - value: function (object) { - if (realHasInstance.call(this, object)) return true; - if (this !== Writable) return false; - - return object && object._writableState instanceof WritableState; - } - }); -} else { - realHasInstance = function (object) { - return object instanceof this; - }; -} - -function Writable(options) { - Duplex = Duplex || __webpack_require__(12); - - // Writable ctor is applied to Duplexes, too. - // `realHasInstance` is necessary because using plain `instanceof` - // would return false, as no `_writableState` property is attached. - - // Trying to use the custom `instanceof` for Writable here will also break the - // Node.js LazyTransform implementation, which has a non-trivial getter for - // `_writableState` that would lead to infinite recursion. - if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { - return new Writable(options); - } - - this._writableState = new WritableState(options, this); - - // legacy. - this.writable = true; - - if (options) { - if (typeof options.write === 'function') this._write = options.write; - - if (typeof options.writev === 'function') this._writev = options.writev; - - if (typeof options.destroy === 'function') this._destroy = options.destroy; - - if (typeof options.final === 'function') this._final = options.final; - } - - Stream.call(this); -} - -// Otherwise people can pipe Writable streams, which is just wrong. -Writable.prototype.pipe = function () { - this.emit('error', new Error('Cannot pipe, not readable')); -}; - -function writeAfterEnd(stream, cb) { - var er = new Error('write after end'); - // TODO: defer error events consistently everywhere, not just the cb - stream.emit('error', er); - pna.nextTick(cb, er); -} - -// Checks that a user-supplied chunk is valid, especially for the particular -// mode the stream is in. Currently this means that `null` is never accepted -// and undefined/non-string values are only allowed in object mode. -function validChunk(stream, state, chunk, cb) { - var valid = true; - var er = false; - - if (chunk === null) { - er = new TypeError('May not write null values to stream'); - } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { - er = new TypeError('Invalid non-string/buffer chunk'); - } - if (er) { - stream.emit('error', er); - pna.nextTick(cb, er); - valid = false; - } - return valid; -} - -Writable.prototype.write = function (chunk, encoding, cb) { - var state = this._writableState; - var ret = false; - var isBuf = !state.objectMode && _isUint8Array(chunk); - - if (isBuf && !Buffer.isBuffer(chunk)) { - chunk = _uint8ArrayToBuffer(chunk); - } - - if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; - - if (typeof cb !== 'function') cb = nop; - - if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { - state.pendingcb++; - ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); - } - - return ret; -}; - -Writable.prototype.cork = function () { - var state = this._writableState; - - state.corked++; -}; - -Writable.prototype.uncork = function () { - var state = this._writableState; - - if (state.corked) { - state.corked--; - - if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); - } -}; - -Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { - // node::ParseEncoding() requires lower case. - if (typeof encoding === 'string') encoding = encoding.toLowerCase(); - if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); - this._writableState.defaultEncoding = encoding; - return this; -}; - -function decodeChunk(state, chunk, encoding) { - if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { - chunk = Buffer.from(chunk, encoding); - } - return chunk; -} - -Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function () { - return this._writableState.highWaterMark; - } -}); - -// if we're already writing something, then just put this -// in the queue, and wait our turn. Otherwise, call _write -// If we return false, then we need a drain event, so set that flag. -function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { - if (!isBuf) { - var newChunk = decodeChunk(state, chunk, encoding); - if (chunk !== newChunk) { - isBuf = true; - encoding = 'buffer'; - chunk = newChunk; - } - } - var len = state.objectMode ? 1 : chunk.length; - - state.length += len; - - var ret = state.length < state.highWaterMark; - // we must ensure that previous needDrain will not be reset to false. - if (!ret) state.needDrain = true; - - if (state.writing || state.corked) { - var last = state.lastBufferedRequest; - state.lastBufferedRequest = { - chunk: chunk, - encoding: encoding, - isBuf: isBuf, - callback: cb, - next: null - }; - if (last) { - last.next = state.lastBufferedRequest; - } else { - state.bufferedRequest = state.lastBufferedRequest; - } - state.bufferedRequestCount += 1; - } else { - doWrite(stream, state, false, len, chunk, encoding, cb); - } - - return ret; -} - -function doWrite(stream, state, writev, len, chunk, encoding, cb) { - state.writelen = len; - state.writecb = cb; - state.writing = true; - state.sync = true; - if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); - state.sync = false; -} - -function onwriteError(stream, state, sync, er, cb) { - --state.pendingcb; - - if (sync) { - // defer the callback if we are being called synchronously - // to avoid piling up things on the stack - pna.nextTick(cb, er); - // this can emit finish, and it will always happen - // after error - pna.nextTick(finishMaybe, stream, state); - stream._writableState.errorEmitted = true; - stream.emit('error', er); - } else { - // the caller expect this to happen before if - // it is async - cb(er); - stream._writableState.errorEmitted = true; - stream.emit('error', er); - // this can emit finish, but finish must - // always follow error - finishMaybe(stream, state); - } -} - -function onwriteStateUpdate(state) { - state.writing = false; - state.writecb = null; - state.length -= state.writelen; - state.writelen = 0; -} - -function onwrite(stream, er) { - var state = stream._writableState; - var sync = state.sync; - var cb = state.writecb; - - onwriteStateUpdate(state); - - if (er) onwriteError(stream, state, sync, er, cb);else { - // Check if we're actually ready to finish, but don't emit yet - var finished = needFinish(state); - - if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { - clearBuffer(stream, state); - } - - if (sync) { - /**/ - asyncWrite(afterWrite, stream, state, finished, cb); - /**/ - } else { - afterWrite(stream, state, finished, cb); - } - } -} - -function afterWrite(stream, state, finished, cb) { - if (!finished) onwriteDrain(stream, state); - state.pendingcb--; - cb(); - finishMaybe(stream, state); -} - -// Must force callback to be called on nextTick, so that we don't -// emit 'drain' before the write() consumer gets the 'false' return -// value, and has a chance to attach a 'drain' listener. -function onwriteDrain(stream, state) { - if (state.length === 0 && state.needDrain) { - state.needDrain = false; - stream.emit('drain'); - } -} - -// if there's something in the buffer waiting, then process it -function clearBuffer(stream, state) { - state.bufferProcessing = true; - var entry = state.bufferedRequest; - - if (stream._writev && entry && entry.next) { - // Fast case, write everything using _writev() - var l = state.bufferedRequestCount; - var buffer = new Array(l); - var holder = state.corkedRequestsFree; - holder.entry = entry; - - var count = 0; - var allBuffers = true; - while (entry) { - buffer[count] = entry; - if (!entry.isBuf) allBuffers = false; - entry = entry.next; - count += 1; - } - buffer.allBuffers = allBuffers; - - doWrite(stream, state, true, state.length, buffer, '', holder.finish); - - // doWrite is almost always async, defer these to save a bit of time - // as the hot path ends with doWrite - state.pendingcb++; - state.lastBufferedRequest = null; - if (holder.next) { - state.corkedRequestsFree = holder.next; - holder.next = null; - } else { - state.corkedRequestsFree = new CorkedRequest(state); - } - state.bufferedRequestCount = 0; - } else { - // Slow case, write chunks one-by-one - while (entry) { - var chunk = entry.chunk; - var encoding = entry.encoding; - var cb = entry.callback; - var len = state.objectMode ? 1 : chunk.length; - - doWrite(stream, state, false, len, chunk, encoding, cb); - entry = entry.next; - state.bufferedRequestCount--; - // if we didn't call the onwrite immediately, then - // it means that we need to wait until it does. - // also, that means that the chunk and cb are currently - // being processed, so move the buffer counter past them. - if (state.writing) { - break; - } - } - - if (entry === null) state.lastBufferedRequest = null; - } - - state.bufferedRequest = entry; - state.bufferProcessing = false; -} - -Writable.prototype._write = function (chunk, encoding, cb) { - cb(new Error('_write() is not implemented')); -}; - -Writable.prototype._writev = null; - -Writable.prototype.end = function (chunk, encoding, cb) { - var state = this._writableState; - - if (typeof chunk === 'function') { - cb = chunk; - chunk = null; - encoding = null; - } else if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); - - // .end() fully uncorks - if (state.corked) { - state.corked = 1; - this.uncork(); - } - - // ignore unnecessary end() calls. - if (!state.ending && !state.finished) endWritable(this, state, cb); -}; - -function needFinish(state) { - return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; -} -function callFinal(stream, state) { - stream._final(function (err) { - state.pendingcb--; - if (err) { - stream.emit('error', err); - } - state.prefinished = true; - stream.emit('prefinish'); - finishMaybe(stream, state); - }); -} -function prefinish(stream, state) { - if (!state.prefinished && !state.finalCalled) { - if (typeof stream._final === 'function') { - state.pendingcb++; - state.finalCalled = true; - pna.nextTick(callFinal, stream, state); - } else { - state.prefinished = true; - stream.emit('prefinish'); - } - } -} - -function finishMaybe(stream, state) { - var need = needFinish(state); - if (need) { - prefinish(stream, state); - if (state.pendingcb === 0) { - state.finished = true; - stream.emit('finish'); - } - } - return need; -} - -function endWritable(stream, state, cb) { - state.ending = true; - finishMaybe(stream, state); - if (cb) { - if (state.finished) pna.nextTick(cb);else stream.once('finish', cb); - } - state.ended = true; - stream.writable = false; -} - -function onCorkedFinish(corkReq, state, err) { - var entry = corkReq.entry; - corkReq.entry = null; - while (entry) { - var cb = entry.callback; - state.pendingcb--; - cb(err); - entry = entry.next; - } - if (state.corkedRequestsFree) { - state.corkedRequestsFree.next = corkReq; - } else { - state.corkedRequestsFree = corkReq; - } -} - -Object.defineProperty(Writable.prototype, 'destroyed', { - get: function () { - if (this._writableState === undefined) { - return false; - } - return this._writableState.destroyed; - }, - set: function (value) { - // we ignore the value if the stream - // has not been initialized yet - if (!this._writableState) { - return; - } - - // backward compatibility, the user is explicitly - // managing destroyed - this._writableState.destroyed = value; - } -}); - -Writable.prototype.destroy = destroyImpl.destroy; -Writable.prototype._undestroy = destroyImpl.undestroy; -Writable.prototype._destroy = function (err, cb) { - this.end(); - cb(err); -}; -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(18), __webpack_require__(179).setImmediate, __webpack_require__(11))) - -/***/ }), -/* 30 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview Implements Editor - * @author NHN FE Development Lab - */ - - -// markdown commands - - -// wysiwyg Commands - - -// langs - - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _button = __webpack_require__(21); - -var _button2 = _interopRequireDefault(_button); - -var _markdownEditor = __webpack_require__(58); - -var _markdownEditor2 = _interopRequireDefault(_markdownEditor); - -var _mdPreview = __webpack_require__(34); - -var _mdPreview2 = _interopRequireDefault(_mdPreview); - -var _wysiwygEditor = __webpack_require__(69); - -var _wysiwygEditor2 = _interopRequireDefault(_wysiwygEditor); - -var _layout = __webpack_require__(83); - -var _layout2 = _interopRequireDefault(_layout); - -var _eventManager = __webpack_require__(40); - -var _eventManager2 = _interopRequireDefault(_eventManager); - -var _commandManager2 = __webpack_require__(2); - -var _commandManager3 = _interopRequireDefault(_commandManager2); - -var _extManager = __webpack_require__(41); - -var _extManager2 = _interopRequireDefault(_extManager); - -var _importManager = __webpack_require__(15); - -var _importManager2 = _interopRequireDefault(_importManager); - -var _wwCodeBlockManager = __webpack_require__(38); - -var _wwCodeBlockManager2 = _interopRequireDefault(_wwCodeBlockManager); - -var _convertor = __webpack_require__(42); - -var _convertor2 = _interopRequireDefault(_convertor); - -var _viewer = __webpack_require__(95); - -var _viewer2 = _interopRequireDefault(_viewer); - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -var _defaultUI = __webpack_require__(96); - -var _defaultUI2 = _interopRequireDefault(_defaultUI); - -var _domUtils = __webpack_require__(4); - -var _domUtils2 = _interopRequireDefault(_domUtils); - -var _wwTableManager = __webpack_require__(36); - -var _wwTableManager2 = _interopRequireDefault(_wwTableManager); - -var _wwTableSelectionManager = __webpack_require__(37); - -var _wwTableSelectionManager2 = _interopRequireDefault(_wwTableSelectionManager); - -var _codeBlockManager = __webpack_require__(25); - -var _codeBlockManager2 = _interopRequireDefault(_codeBlockManager); - -var _toMarkRenderer = __webpack_require__(113); - -var _toMarkRenderer2 = _interopRequireDefault(_toMarkRenderer); - -var _bold = __webpack_require__(114); - -var _bold2 = _interopRequireDefault(_bold); - -var _italic = __webpack_require__(115); - -var _italic2 = _interopRequireDefault(_italic); - -var _strike = __webpack_require__(116); - -var _strike2 = _interopRequireDefault(_strike); - -var _blockquote = __webpack_require__(117); - -var _blockquote2 = _interopRequireDefault(_blockquote); - -var _heading = __webpack_require__(118); - -var _heading2 = _interopRequireDefault(_heading); - -var _paragraph = __webpack_require__(119); - -var _paragraph2 = _interopRequireDefault(_paragraph); - -var _hr = __webpack_require__(120); - -var _hr2 = _interopRequireDefault(_hr); - -var _addLink = __webpack_require__(121); - -var _addLink2 = _interopRequireDefault(_addLink); - -var _addImage = __webpack_require__(122); - -var _addImage2 = _interopRequireDefault(_addImage); - -var _ul = __webpack_require__(123); - -var _ul2 = _interopRequireDefault(_ul); - -var _ol = __webpack_require__(124); - -var _ol2 = _interopRequireDefault(_ol); - -var _indent = __webpack_require__(125); - -var _indent2 = _interopRequireDefault(_indent); - -var _outdent = __webpack_require__(126); - -var _outdent2 = _interopRequireDefault(_outdent); - -var _table = __webpack_require__(127); - -var _table2 = _interopRequireDefault(_table); - -var _task = __webpack_require__(128); - -var _task2 = _interopRequireDefault(_task); - -var _code = __webpack_require__(129); - -var _code2 = _interopRequireDefault(_code); - -var _codeBlock = __webpack_require__(130); - -var _codeBlock2 = _interopRequireDefault(_codeBlock); - -var _bold3 = __webpack_require__(131); - -var _bold4 = _interopRequireDefault(_bold3); - -var _italic3 = __webpack_require__(132); - -var _italic4 = _interopRequireDefault(_italic3); - -var _strike3 = __webpack_require__(133); - -var _strike4 = _interopRequireDefault(_strike3); - -var _blockquote3 = __webpack_require__(134); - -var _blockquote4 = _interopRequireDefault(_blockquote3); - -var _addImage3 = __webpack_require__(135); - -var _addImage4 = _interopRequireDefault(_addImage3); - -var _addLink3 = __webpack_require__(136); - -var _addLink4 = _interopRequireDefault(_addLink3); - -var _hr3 = __webpack_require__(137); - -var _hr4 = _interopRequireDefault(_hr3); - -var _heading3 = __webpack_require__(138); - -var _heading4 = _interopRequireDefault(_heading3); - -var _paragraph3 = __webpack_require__(139); - -var _paragraph4 = _interopRequireDefault(_paragraph3); - -var _ul3 = __webpack_require__(140); - -var _ul4 = _interopRequireDefault(_ul3); - -var _ol3 = __webpack_require__(141); - -var _ol4 = _interopRequireDefault(_ol3); - -var _table3 = __webpack_require__(142); - -var _table4 = _interopRequireDefault(_table3); - -var _tableAddRow = __webpack_require__(143); - -var _tableAddRow2 = _interopRequireDefault(_tableAddRow); - -var _tableAddCol = __webpack_require__(144); - -var _tableAddCol2 = _interopRequireDefault(_tableAddCol); - -var _tableRemoveRow = __webpack_require__(145); - -var _tableRemoveRow2 = _interopRequireDefault(_tableRemoveRow); - -var _tableRemoveCol = __webpack_require__(146); - -var _tableRemoveCol2 = _interopRequireDefault(_tableRemoveCol); - -var _tableAlignCol = __webpack_require__(147); - -var _tableAlignCol2 = _interopRequireDefault(_tableAlignCol); - -var _tableRemove = __webpack_require__(148); - -var _tableRemove2 = _interopRequireDefault(_tableRemove); - -var _indent3 = __webpack_require__(149); - -var _indent4 = _interopRequireDefault(_indent3); - -var _outdent3 = __webpack_require__(150); - -var _outdent4 = _interopRequireDefault(_outdent3); - -var _task3 = __webpack_require__(151); - -var _task4 = _interopRequireDefault(_task3); - -var _code3 = __webpack_require__(152); - -var _code4 = _interopRequireDefault(_code3); - -var _codeBlock3 = __webpack_require__(153); - -var _codeBlock4 = _interopRequireDefault(_codeBlock3); - -__webpack_require__(154); - -__webpack_require__(155); - -__webpack_require__(156); - -__webpack_require__(157); - -__webpack_require__(158); - -__webpack_require__(159); - -__webpack_require__(160); - -__webpack_require__(161); - -__webpack_require__(162); - -__webpack_require__(163); - -__webpack_require__(164); - -__webpack_require__(165); - -__webpack_require__(166); - -__webpack_require__(167); - -__webpack_require__(168); - -__webpack_require__(169); - -__webpack_require__(170); - -__webpack_require__(171); - -__webpack_require__(172); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var __nedInstance = []; -var gaTrackingId = 'UA-129966929-1'; - -var availableLinkAttributes = ['rel', 'target', 'contenteditable', 'hreflang', 'type']; - -/** - * @callback addImageBlobHook - * @param {File|Blob} fileOrBlob - image blob - * @param {callback} callback - callback function to be called after - * @param {string} source - source of an event the item belongs to. 'paste', 'drop', 'ui' - */ - -/** - * ToastUI Editor - * @param {object} options Option object - * @param {HTMLElement} options.el - container element - * @param {string} [options.height='300px'] - Editor's height style value. Height is applied as border-box ex) '300px', '100%', 'auto' - * @param {string} [options.minHeight='200px'] - Editor's min-height style value in pixel ex) '300px' - * @param {string} [options.initialValue] - Editor's initial value - * @param {string} [options.previewStyle] - Markdown editor's preview style (tab, vertical) - * @param {string} [options.initialEditType] - Initial editor type (markdown, wysiwyg) - * @param {object[]} [options.events] - eventlist Event list - * @param {function} options.events.load - It would be emitted when editor fully load - * @param {function} options.events.change - It would be emitted when content changed - * @param {function} options.events.stateChange - It would be emitted when format change by cursor position - * @param {function} options.events.focus - It would be emitted when editor get focus - * @param {function} options.events.blur - It would be emitted when editor loose focus - * @param {object[]} [options.hooks] - Hook list - * @param {function} options.hooks.previewBeforeHook - Submit preview to hook URL before preview be shown - * @param {addImageBlobHook} options.hooks.addImageBlobHook - hook for image upload. - * @param {string} [options.language='en_US'] - language - * @param {boolean} [options.useCommandShortcut=true] - whether use keyboard shortcuts to perform commands - * @param {boolean} [options.useDefaultHTMLSanitizer=true] - use default htmlSanitizer - * @param {string[]} [options.codeBlockLanguages] - supported code block languages to be listed. default is what highlight.js supports - * @param {boolean} [options.usageStatistics=true] - send hostname to google analytics - * @param {string[]} [options.toolbarItems] - toolbar items. - * @param {boolean} [options.hideModeSwitch=false] - hide mode switch tab bar - * @param {string[]} [options.exts] - extensions - * @param {object} [options.customConvertor] - convertor extention - * @param {string} [options.placeholder] - The placeholder text of the editable element. - * @param {string} [options.previewDelayTime] - the delay time for rendering preview - * @param {object} [options.linkAttribute] - Attributes of anchor element that shold be rel, target, contenteditable, hreflang, type - */ - -var ToastUIEditor = function () { - function ToastUIEditor(options) { - var _this = this; - - _classCallCheck(this, ToastUIEditor); - - this.initialHtml = options.el.innerHTML; - options.el.innerHTML = ''; - - this.options = _jquery2.default.extend({ - previewStyle: 'tab', - initialEditType: 'markdown', - height: '300px', - minHeight: '200px', - language: 'en_US', - useDefaultHTMLSanitizer: true, - useCommandShortcut: true, - codeBlockLanguages: _codeBlockManager.CodeBlockManager.getHighlightJSLanguages(), - usageStatistics: true, - toolbarItems: ['heading', 'bold', 'italic', 'strike', 'divider', 'hr', 'quote', 'divider', 'ul', 'ol', 'task', 'indent', 'outdent', 'divider', 'table', 'image', 'link', 'divider', 'code', 'codeblock'], - hideModeSwitch: false, - customConvertor: null - }, options); - - this.eventManager = new _eventManager2.default(); - - this.importManager = new _importManager2.default(this.eventManager); - - this.commandManager = new _commandManager3.default(this, { - useCommandShortcut: this.options.useCommandShortcut - }); - - if (this.options.customConvertor) { - // eslint-disable-next-line new-cap - this.convertor = new this.options.customConvertor(this.eventManager); - } else { - this.convertor = new _convertor2.default(this.eventManager); - } - - if (this.options.useDefaultHTMLSanitizer) { - this.convertor.initHtmlSanitizer(); - } - - if (this.options.hooks) { - _tuiCodeSnippet2.default.forEach(this.options.hooks, function (fn, key) { - return _this.addHook(key, fn); - }); - } - - if (this.options.events) { - _tuiCodeSnippet2.default.forEach(this.options.events, function (fn, key) { - return _this.on(key, fn); - }); - } - - this.layout = new _layout2.default(options, this.eventManager); - - this.i18n = _i18n2.default; - this.i18n.setCode(this.options.language); - - this.setUI(this.options.UI || new _defaultUI2.default(this)); - - this.mdEditor = _markdownEditor2.default.factory(this.layout.getMdEditorContainerEl(), this.eventManager, this.options); - this.preview = new _mdPreview2.default(this.layout.getPreviewEl(), this.eventManager, this.convertor, false, this.options.previewDelayTime); - this.wwEditor = _wysiwygEditor2.default.factory(this.layout.getWwEditorContainerEl(), this.eventManager, { - useDefaultHTMLSanitizer: this.options.useDefaultHTMLSanitizer - }); - this.toMarkOptions = { - gfm: true, - renderer: _toMarkRenderer2.default - }; - - if (this.options.linkAttribute) { - var attribute = this._sanitizeLinkAttribute(this.options.linkAttribute); - - this.convertor.setLinkAttribute(attribute); - this.wwEditor.setLinkAttribute(attribute); - } - - this.changePreviewStyle(this.options.previewStyle); - - this.changeMode(this.options.initialEditType, true); - - this.minHeight(this.options.minHeight); - - this.height(this.options.height); - - this.setValue(this.options.initialValue, false); - - if (this.options.placeholder) { - this.setPlaceholder(this.options.placeholder); - } - - if (!this.options.initialValue) { - this.setHtml(this.initialHtml, false); - } - - _extManager2.default.applyExtension(this, this.options.exts); - - this.eventManager.emit('load', this); - - __nedInstance.push(this); - - this._addDefaultCommands(); - - if (this.options.usageStatistics) { - _tuiCodeSnippet2.default.sendHostname('editor', gaTrackingId); - } - } - - /** - * sanitize attribute for link - * @param {object} attribute - attribute for link - * @returns {object} sanitized attribute - * @private - */ - - - _createClass(ToastUIEditor, [{ - key: '_sanitizeLinkAttribute', - value: function _sanitizeLinkAttribute(attribute) { - var linkAttribute = {}; - - availableLinkAttributes.forEach(function (key) { - if (!_tuiCodeSnippet2.default.isUndefined(attribute[key])) { - linkAttribute[key] = attribute[key]; - } - }); - - return linkAttribute; - } - - /** - * change preview style - * @param {string} style - 'tab'|'vertical' - */ - - }, { - key: 'changePreviewStyle', - value: function changePreviewStyle(style) { - this.layout.changePreviewStyle(style); - this.mdPreviewStyle = style; - this.eventManager.emit('changePreviewStyle', style); - this.eventManager.emit('previewNeedsRefresh'); - } - - /** - * call commandManager's exec method - * @param {*} ...args Command argument - */ - - }, { - key: 'exec', - value: function exec() { - var _commandManager; - - (_commandManager = this.commandManager).exec.apply(_commandManager, arguments); - } - - /** - * add default commands - * @private - */ - - }, { - key: '_addDefaultCommands', - value: function _addDefaultCommands() { - this.addCommand(_bold2.default); - this.addCommand(_italic2.default); - this.addCommand(_blockquote2.default); - this.addCommand(_heading2.default); - this.addCommand(_paragraph2.default); - this.addCommand(_hr2.default); - this.addCommand(_addLink2.default); - this.addCommand(_addImage2.default); - this.addCommand(_ul2.default); - this.addCommand(_ol2.default); - this.addCommand(_indent2.default); - this.addCommand(_outdent2.default); - this.addCommand(_table2.default); - this.addCommand(_task2.default); - this.addCommand(_code2.default); - this.addCommand(_codeBlock2.default); - this.addCommand(_strike2.default); - - this.addCommand(_bold4.default); - this.addCommand(_italic4.default); - this.addCommand(_blockquote4.default); - this.addCommand(_ul4.default); - this.addCommand(_ol4.default); - this.addCommand(_addImage4.default); - this.addCommand(_addLink4.default); - this.addCommand(_hr4.default); - this.addCommand(_heading4.default); - this.addCommand(_paragraph4.default); - this.addCommand(_indent4.default); - this.addCommand(_outdent4.default); - this.addCommand(_task4.default); - this.addCommand(_table4.default); - this.addCommand(_tableAddRow2.default); - this.addCommand(_tableAddCol2.default); - this.addCommand(_tableRemoveRow2.default); - this.addCommand(_tableRemoveCol2.default); - this.addCommand(_tableAlignCol2.default); - this.addCommand(_tableRemove2.default); - this.addCommand(_code4.default); - this.addCommand(_codeBlock4.default); - this.addCommand(_strike4.default); - } - }, { - key: 'addCommand', - value: function addCommand(type, props) { - if (!props) { - this.commandManager.addCommand(type); - } else { - this.commandManager.addCommand(_commandManager3.default.command(type, props)); - } - } - - /** - * After added command. - */ - - }, { - key: 'afterAddedCommand', - value: function afterAddedCommand() { - this.eventManager.emit('afterAddedCommand', this); - } - - /** - * Bind eventHandler to event type - * @param {string} type Event type - * @param {function} handler Event handler - */ - - }, { - key: 'on', - value: function on(type, handler) { - this.eventManager.listen(type, handler); - } - - /** - * Unbind eventHandler from event type - * @param {string} type Event type - */ - - }, { - key: 'off', - value: function off(type) { - this.eventManager.removeEventHandler(type); - } - - /** - * Add hook to TUIEditor event - * @param {string} type Event type - * @param {function} handler Event handler - */ - - }, { - key: 'addHook', - value: function addHook(type, handler) { - this.eventManager.removeEventHandler(type); - this.eventManager.listen(type, handler); - } - - /** - * Remove hook from TUIEditor event - * @param {string} type Event type - */ - - }, { - key: 'removeHook', - value: function removeHook(type) { - this.eventManager.removeEventHandler(type); - } - - /** - * Get CodeMirror instance - * @returns {CodeMirror} - */ - - }, { - key: 'getCodeMirror', - value: function getCodeMirror() { - return this.mdEditor.getEditor(); - } - - /** - * Get SquireExt instance - * @returns {SquireExt} - */ - - }, { - key: 'getSquire', - value: function getSquire() { - return this.wwEditor.getEditor(); - } - - /** - * Set focus to current Editor - */ - - }, { - key: 'focus', - value: function focus() { - this.getCurrentModeEditor().focus(); - } - - /** - * Remove focus of current Editor - */ - - }, { - key: 'blur', - value: function blur() { - this.getCurrentModeEditor().blur(); - } - - /** - * Set cursor position to end - */ - - }, { - key: 'moveCursorToEnd', - value: function moveCursorToEnd() { - this.getCurrentModeEditor().moveCursorToEnd(); - } - - /** - * Set cursor position to start - */ - - }, { - key: 'moveCursorToStart', - value: function moveCursorToStart() { - this.getCurrentModeEditor().moveCursorToStart(); - } - - /** - * Set markdown syntax text. - * @param {string} markdown - markdown syntax text. - * @param {boolean} [cursorToEnd=true] - move cursor to contents end - */ - - }, { - key: 'setMarkdown', - value: function setMarkdown(markdown) { - var cursorToEnd = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - - markdown = markdown || ''; - - if (this.isMarkdownMode()) { - this.mdEditor.setValue(markdown, cursorToEnd); - } else { - this.wwEditor.setValue(this.convertor.toHTML(markdown), cursorToEnd); - } - - this.eventManager.emit('setMarkdownAfter', markdown); - } - - /** - * Set html value. - * @param {string} html - html syntax text - * @param {boolean} [cursorToEnd=true] - move cursor to contents end - */ - - }, { - key: 'setHtml', - value: function setHtml(html) { - var cursorToEnd = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - - html = html || ''; - this.wwEditor.setValue(html, cursorToEnd); - - if (this.isMarkdownMode()) { - var markdown = this.convertor.toMarkdown(this.wwEditor.getValue(), this.toMarkOptions); - this.mdEditor.setValue(markdown, cursorToEnd); - this.eventManager.emit('setMarkdownAfter', markdown); - } - } - - /** - * Set markdown syntax text. - * @param {string} value - markdown syntax text - * @param {boolean} [cursorToEnd=true] - move cursor to contents end - * @deprecated - */ - - }, { - key: 'setValue', - value: function setValue(value) { - var cursorToEnd = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - - this.setMarkdown(value, cursorToEnd); - } - - /** - * Get markdown syntax text. - * @returns {string} - */ - - }, { - key: 'getMarkdown', - value: function getMarkdown() { - var markdown = void 0; - - if (this.isMarkdownMode()) { - markdown = this.mdEditor.getValue(); - } else { - markdown = this.convertor.toMarkdown(this.wwEditor.getValue(), this.toMarkOptions); - } - - return markdown; - } - - /** - * Get html syntax text. - * @returns {string} - */ - - }, { - key: 'getHtml', - value: function getHtml() { - if (this.isWysiwygMode()) { - this.mdEditor.setValue(this.convertor.toMarkdown(this.wwEditor.getValue(), this.toMarkOptions)); - } - - return this.convertor.toHTML(this.mdEditor.getValue()); - } - - /** - * Get editor value. - * @returns {string} - * @deprecated - */ - - }, { - key: 'getValue', - value: function getValue() { - return this.getMarkdown(); - } - - /** - * Insert text - * @param {string} text - text string to insert - */ - - }, { - key: 'insertText', - value: function insertText(text) { - if (this.isMarkdownMode()) { - this.mdEditor.replaceSelection(text); - } else { - this.wwEditor.insertText(text); - } - } - - /** - * Add widget to selection - * @param {Range} selection Current selection - * @param {Node} node widget node - * @param {string} style Adding style "over" or "bottom" - * @param {number} [offset] Offset for adjust position - */ - - }, { - key: 'addWidget', - value: function addWidget(selection, node, style, offset) { - this.getCurrentModeEditor().addWidget(selection, node, style, offset); - } - - /** - * Set and return edithr height - * @param {string} height - editor height - * @returns {string} editor height - */ - - }, { - key: 'height', - value: function height(_height) { - if (_tuiCodeSnippet2.default.isExisty(_height)) { - if (_height === 'auto') { - (0, _jquery2.default)(this.options.el).addClass('auto-height'); - this.minHeight(this.minHeight()); - } else { - (0, _jquery2.default)(this.options.el).removeClass('auto-height'); - this.minHeight(_height); - } - if (_tuiCodeSnippet2.default.isNumber(_height)) { - _height = _height + 'px'; - } - - this.options.el.style.height = _height; - this._height = _height; - } - - return this._height; - } - - /** - * Set / Get min content height - * @param {string} minHeight - min content height in pixel - * @returns {string} - min height in pixel - */ - - }, { - key: 'minHeight', - value: function minHeight(_minHeight) { - if (_tuiCodeSnippet2.default.isExisty(_minHeight)) { - var editorHeight = this._ui.getEditorHeight(); - var editorSectionHeight = this._ui.getEditorSectionHeight(); - var diffHeight = editorHeight - editorSectionHeight; - this._minHeight = _minHeight; - - _minHeight = parseInt(_minHeight, 10); - _minHeight = Math.max(_minHeight - diffHeight, 0); - - this.wwEditor.setMinHeight(_minHeight); - this.mdEditor.setMinHeight(_minHeight); - this.preview.setMinHeight(_minHeight); - } - - return this._minHeight; - } - - /** - * Get current editor mode name - * @returns {Object} MarkdownEditor or WysiwygEditor - */ - - }, { - key: 'getCurrentModeEditor', - value: function getCurrentModeEditor() { - var editor = void 0; - - if (this.isMarkdownMode()) { - editor = this.mdEditor; - } else { - editor = this.wwEditor; - } - - return editor; - } - - /** - * Return true if current editor mode is Markdown - * @returns {boolean} - */ - - }, { - key: 'isMarkdownMode', - value: function isMarkdownMode() { - return this.currentMode === 'markdown'; - } - - /** - * Return true if current editor mode is WYSIWYG - * @returns {boolean} - */ - - }, { - key: 'isWysiwygMode', - value: function isWysiwygMode() { - return this.currentMode === 'wysiwyg'; - } - - /** - * Return false - * @returns {boolean} - */ - - }, { - key: 'isViewer', - value: function isViewer() { - return false; - } - - /** - * Get current Markdown editor's preview style - * @returns {string} - */ - - }, { - key: 'getCurrentPreviewStyle', - value: function getCurrentPreviewStyle() { - return this.mdPreviewStyle; - } - - /** - * Change editor's mode to given mode string - * @param {string} mode - Editor mode name of want to change - * @param {boolean} [isWithoutFocus] - Change mode without focus - */ - - }, { - key: 'changeMode', - value: function changeMode(mode, isWithoutFocus) { - if (this.currentMode === mode) { - return; - } - - this.eventManager.emit('changeModeBefore', this.currentMode); - - this.currentMode = mode; - - if (this.isWysiwygMode()) { - this.layout.switchToWYSIWYG(); - this.wwEditor.setValue(this.convertor.toHTML(this.mdEditor.getValue()), !isWithoutFocus); - this.eventManager.emit('changeModeToWysiwyg'); - } else { - this.layout.switchToMarkdown(); - this.mdEditor.resetState(); - this.mdEditor.setValue(this.convertor.toMarkdown(this.wwEditor.getValue(), this.toMarkOptions), !isWithoutFocus); - this.getCodeMirror().refresh(); - this.eventManager.emit('changeModeToMarkdown'); - } - - this.eventManager.emit('changeMode', mode); - - if (!isWithoutFocus) { - this.focus(); - } - } - - /** - * Remove TUIEditor from document - */ - - }, { - key: 'remove', - value: function remove() { - var self = this; - var i = __nedInstance.length - 1; - this.wwEditor.remove(); - this.mdEditor.remove(); - this.layout.remove(); - this.preview.remove(); - - if (this.getUI()) { - this.getUI().remove(); - } - - this.eventManager.emit('removeEditor'); - this.eventManager.events.forEach(function (value, key) { - self.off(key); - }); - this.eventManager = null; - - for (; i >= 0; i -= 1) { - if (__nedInstance[i] === this) { - __nedInstance.splice(i, 1); - } - } - } - - /** - * Hide TUIEditor - */ - - }, { - key: 'hide', - value: function hide() { - this.eventManager.emit('hide', this); - } - - /** - * Show TUIEditor - */ - - }, { - key: 'show', - value: function show() { - this.eventManager.emit('show', this); - this.getCodeMirror().refresh(); - } - - /** - * Scroll Editor content to Top - * @param {number} value Scroll amount - * @returns {number} - */ - - }, { - key: 'scrollTop', - value: function scrollTop(value) { - return this.getCurrentModeEditor().scrollTop(value); - } - - /** - * Set UI to private UI property - * @param {UI} UI UI instance - */ - - }, { - key: 'setUI', - value: function setUI(UI) { - this._ui = UI; - } - - /** - * Get _ui property - * @returns {DefaultUI|UI} - */ - - }, { - key: 'getUI', - value: function getUI() { - return this._ui; - } - - /** - * Reset TUIEditor - */ - - }, { - key: 'reset', - value: function reset() { - this.wwEditor.reset(); - this.mdEditor.reset(); - } - - /** - * Get current range - * @returns {{start, end}|Range} - */ - - }, { - key: 'getRange', - value: function getRange() { - return this.getCurrentModeEditor().getRange(); - } - - /** - * Get text object of current range - * @param {{start, end}|Range} range Range object of each editor - * @returns {MdTextObject|WwTextObject} TextObject class - */ - - }, { - key: 'getTextObject', - value: function getTextObject(range) { - return this.getCurrentModeEditor().getTextObject(range); - } - - /** - * get selected text - * @returns {string} - selected text - */ - - }, { - key: 'getSelectedText', - value: function getSelectedText() { - var range = this.getRange(); - var textObject = this.getTextObject(range); - - return textObject.getTextContent() || ''; - } - - /** - * Set the placeholder on all editors - * @param {string} placeholder - placeholder to set - */ - - }, { - key: 'setPlaceholder', - value: function setPlaceholder(placeholder) { - this.mdEditor.setPlaceholder(placeholder); - this.wwEditor.setPlaceholder(placeholder); - } - - /** - * Get instance of TUIEditor - * @returns {Array} - */ - - }], [{ - key: 'getInstances', - value: function getInstances() { - return __nedInstance; - } - - /** - * Define extension - * @param {string} name Extension name - * @param {function} ext extension - */ - - }, { - key: 'defineExtension', - value: function defineExtension(name, ext) { - _extManager2.default.defineExtension(name, ext); - } - - /** - * Factory method for Editor - * @param {object} options Option for initialize TUIEditor - * @returns {object} ToastUIEditor or ToastUIEditorViewer - */ - - }, { - key: 'factory', - value: function factory(options) { - var tuiEditor = void 0; - - if (options.viewer) { - tuiEditor = new _viewer2.default(options); - } else { - tuiEditor = new ToastUIEditor(options); - } - - return tuiEditor; - } - }]); - - return ToastUIEditor; -}(); - -/** - * check whther is viewer - * @type {boolean} - */ - - -ToastUIEditor.isViewer = false; - -/** - * I18n instance - * @type {I18n} - */ -ToastUIEditor.i18n = _i18n2.default; - -/** - * domUtil instance - * @type {DomUtil} - * @ignore - */ -ToastUIEditor.domUtils = _domUtils2.default; - -/** - * CodeBlockManager instance - * @type {CodeBlockManager} - */ -ToastUIEditor.codeBlockManager = _codeBlockManager2.default; - -/** - * Button class - * @type {Class.'); - this.$el.append(this._$buttonOpenModalEditor); - this._eventManager.emit('removeEditor', function () { - _this2._$buttonOpenModalEditor.off('click'); - _this2._$buttonOpenModalEditor = null; - }); - } - }, { - key: '_initDOMEvent', - value: function _initDOMEvent() { - var _this3 = this; - - this._$buttonOpenModalEditor.on('click', function () { - return _this3._openPopupCodeBlockEditor(); - }); - } - }, { - key: '_openPopupCodeBlockEditor', - value: function _openPopupCodeBlockEditor() { - this._eventManager.emit('openPopupCodeBlockEditor', this.getAttachedElement()); - } - }, { - key: '_updateLanguage', - value: function _updateLanguage() { - var attachedElement = this.getAttachedElement(); - var language = attachedElement ? attachedElement.getAttribute('data-language') : null; - - this._$languageLabel.text(language ? language : 'text'); - } - - /** - * update gadget position - * @protected - * @override - */ - - }, { - key: 'syncLayout', - value: function syncLayout() { - var $attachedElement = (0, _jquery2.default)(this.getAttachedElement()); - var offset = $attachedElement.offset(); - - offset.left = offset.left + ($attachedElement.outerWidth() - GADGET_WIDTH); - - this.$el.offset(offset); - this.$el.height(GADGET_HEIGHT); - this.$el.width(GADGET_WIDTH); - } - - /** - * on show - * @protected - * @override - */ - - }, { - key: 'onShow', - value: function onShow() { - var _this4 = this; - - _get(CodeBlockGadget.prototype.__proto__ || Object.getPrototypeOf(CodeBlockGadget.prototype), 'onShow', this).call(this); - - this._onAttachedElementChange = function () { - return _this4._updateLanguage(); - }; - (0, _jquery2.default)(this.getAttachedElement()).on(EVENT_LANGUAGE_CHANGED, this._onAttachedElementChange); - - this._updateLanguage(); - } - - /** - * on hide - * @protected - * @override - */ - - }, { - key: 'onHide', - value: function onHide() { - (0, _jquery2.default)(this.getAttachedElement()).off(EVENT_LANGUAGE_CHANGED, this._onAttachedElementChange); - - _get(CodeBlockGadget.prototype.__proto__ || Object.getPrototypeOf(CodeBlockGadget.prototype), 'onHide', this).call(this); - } - }]); - - return CodeBlockGadget; -}(_blockOverlay2.default); - -exports.default = CodeBlockGadget; - -/***/ }), -/* 82 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview Implements UI block overlay - * @author NHN FE Development Lab - */ - - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Class BlockOverlay - * @param {Object} options - options - * @param {EventManager} options.eventManager - event manager instance - * @param {HTMLElement} options.container - container element - * @param {string} options.attachedSelector - selector string to find attached element - * @ignore - */ -var BlockOverlay = function () { - function BlockOverlay(_ref) { - var eventManager = _ref.eventManager, - container = _ref.container, - attachedSelector = _ref.attachedSelector; - - _classCallCheck(this, BlockOverlay); - - this._eventManager = eventManager; - this._attachedSelector = '[contenteditable=true] ' + attachedSelector; - this._$container = (0, _jquery2.default)(container); - this._$attachedElement = null; - - /** - * is activated. - * if this blockOverlay is active, It always be visible unconditionally. - * @type {boolean} - * @private - */ - this.active = false; - - this._createElement(); - this._initEvent(); - } - - _createClass(BlockOverlay, [{ - key: '_createElement', - value: function _createElement() { - this.$el = (0, _jquery2.default)('
    '); - this.$el.css({ - position: 'absolute', - display: 'none', - 'z-index': 1 - }); - this._$container.append(this.$el); - } - }, { - key: '_initEvent', - value: function _initEvent() { - var _this = this; - - this._eventManager.listen('change', this._onChange.bind(this)); - this._eventManager.listen('mouseover', this._onMouseOver.bind(this)); - this._eventManager.listen('focus', function () { - _this.setVisibility(false); - }); - this._eventManager.listen('mousedown', function () { - _this.setVisibility(false); - }); - } - }, { - key: '_onChange', - value: function _onChange() { - if (this._$attachedElement && _jquery2.default.contains(document, this._$attachedElement[0])) { - this.syncLayout(); - } else { - this.setVisibility(false); - } - } - }, { - key: '_onMouseOver', - value: function _onMouseOver(ev) { - var originalEvent = ev.data; - var $eventTarget = (0, _jquery2.default)(originalEvent.target); - var $attachedElement = $eventTarget.closest(this._attachedSelector); - - if ($attachedElement.length) { - this._$attachedElement = $attachedElement; - this.setVisibility(true); - } else if ($eventTarget.closest(this.$el).length) { - this.setVisibility(true); - } else if (!this.active) { - this.setVisibility(false); - } - } - - /** - * update blockOverlay position & size update to attached element - * you may want to override this to adjust position & size - * @protected - */ - - }, { - key: 'syncLayout', - value: function syncLayout() { - this.$el.offset(this._$attachedElement.offset()); - this.$el.width(this._$attachedElement.outerWidth()); - this.$el.height(this._$attachedElement.outerHeight()); - } - - /** - * attached element - * @protected - * @returns {HTMLElement} - attached element - */ - - }, { - key: 'getAttachedElement', - value: function getAttachedElement() { - return this._$attachedElement ? this._$attachedElement.get(0) : null; - } - - /** - * visibility - * @protected - * @returns {boolean} visibility - */ - - }, { - key: 'getVisibility', - value: function getVisibility() { - return this.$el.css('display') === 'block'; - } - - /** - * visibility - * @param {boolean} visibility - is visible - * @protected - */ - - }, { - key: 'setVisibility', - value: function setVisibility(visibility) { - if (visibility && this._$attachedElement) { - if (!this.getVisibility()) { - this.$el.css('display', 'block'); - this.syncLayout(); - this.onShow(); - } - } else if (!visibility) { - if (this.getVisibility()) { - this.$el.css('display', 'none'); - this.onHide(); - } - } - } - - /** - * called on show. you may want to override to get the event - * @protected - * @abstract - */ - - }, { - key: 'onShow', - value: function onShow() {} - - /** - * called on hide. you may want to override to get the event - * @protected - */ - - }, { - key: 'onHide', - value: function onHide() { - this.active = false; - this._$attachedElement = null; - } - }]); - - return BlockOverlay; -}(); - -exports.default = BlockOverlay; - -/***/ }), -/* 83 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview editor layout - * @author NHN FE Development Lab - */ - - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Editor container template - * @type {string} - * @ignore - */ -var containerTmpl = ['
    ', '
    ', '
    ', '
    ', '
    ', '
    ', '
    ', '
    ', '
    ', '
    '].join(''); - -/** - * Class Layout - * @param {object} options - Option object - * @param {EventManager} eventManager - Event manager instance - * @ignore - */ - -var Layout = function () { - function Layout(options, eventManager) { - _classCallCheck(this, Layout); - - this.$el = (0, _jquery2.default)(options.el); - this.height = options.height; - this.type = options.initialEditType; - this.eventManager = eventManager; - - this.init(); - this._initEvent(); - } - - /** - * Initializer - * @protected - */ - - - _createClass(Layout, [{ - key: 'init', - value: function init() { - this._renderLayout(); - - this._initMarkdownAndPreviewSection(); - this._initWysiwygSection(); - } - - /** - * Initialize show and hide event - * @private - */ - - }, { - key: '_initEvent', - value: function _initEvent() { - this.eventManager.listen('hide', this.hide.bind(this)); - this.eventManager.listen('show', this.show.bind(this)); - } - - /** - * Create editor container with template - * @private - */ - - }, { - key: '_renderLayout', - value: function _renderLayout() { - this.$el.css('box-sizing', 'border-box'); - this.$containerEl = (0, _jquery2.default)(containerTmpl).appendTo(this.$el); - } - - /** - * Switch editor mode to WYSIWYG - */ - - }, { - key: 'switchToWYSIWYG', - value: function switchToWYSIWYG() { - this.$containerEl.removeClass('te-md-mode'); - this.$containerEl.addClass('te-ww-mode'); - } - - /** - * Switch editor mode to Markdown - */ - - }, { - key: 'switchToMarkdown', - value: function switchToMarkdown() { - this.$containerEl.removeClass('te-ww-mode'); - this.$containerEl.addClass('te-md-mode'); - } - - /** - * Initialize editor to Markdown and set preview section - * @private - */ - - }, { - key: '_initMarkdownAndPreviewSection', - value: function _initMarkdownAndPreviewSection() { - this.$mdEditorContainerEl = this.$containerEl.find('.te-md-container .te-editor'); - this.$previewEl = this.$containerEl.find('.te-md-container .te-preview'); - } - - /** - * Initialize editor to WYSIWYG - * @private - */ - - }, { - key: '_initWysiwygSection', - value: function _initWysiwygSection() { - this.$wwEditorContainerEl = this.$containerEl.find('.te-ww-container .te-editor'); - } - - /** - * Set preview to vertical split style - * @private - */ - - }, { - key: '_verticalSplitStyle', - value: function _verticalSplitStyle() { - this.$containerEl.find('.te-md-container').removeClass('te-preview-style-tab'); - this.$containerEl.find('.te-md-container').addClass('te-preview-style-vertical'); - } - - /** - * Set tab style preview mode - * @private - */ - - }, { - key: '_tabStyle', - value: function _tabStyle() { - this.$containerEl.find('.te-md-container').removeClass('te-preview-style-vertical'); - this.$containerEl.find('.te-md-container').addClass('te-preview-style-tab'); - } - - /** - * Toggle preview style between tab and vertical split - * @param {string} style Preview style ('tab' or 'vertical') - */ - - }, { - key: 'changePreviewStyle', - value: function changePreviewStyle(style) { - if (style === 'tab') { - this._tabStyle(); - } else if (style === 'vertical') { - this._verticalSplitStyle(); - } - } - - /** - * Hide Editor - */ - - }, { - key: 'hide', - value: function hide() { - this.$el.find('.tui-editor').addClass('te-hide'); - } - - /** - * Show Editor - */ - - }, { - key: 'show', - value: function show() { - this.$el.find('.tui-editor').removeClass('te-hide'); - } - - /** - * Remove Editor - */ - - }, { - key: 'remove', - value: function remove() { - this.$el.find('.tui-editor').remove(); - } - - /** - * Get jQuery wrapped editor container element - * @returns {jQuery} - */ - - }, { - key: 'getEditorEl', - value: function getEditorEl() { - return this.$containerEl; - } - - /** - * Get jQuery wrapped preview element - * @returns {jQuery} - */ - - }, { - key: 'getPreviewEl', - value: function getPreviewEl() { - return this.$previewEl; - } - - /** - * Get jQuery wrapped Markdown editor element - * @returns {jQuery} - */ - - }, { - key: 'getMdEditorContainerEl', - value: function getMdEditorContainerEl() { - return this.$mdEditorContainerEl; - } - - /** - * Get jQuery wrapped WYSIWYG editor element - * @returns {jQuery} - */ - - }, { - key: 'getWwEditorContainerEl', - value: function getWwEditorContainerEl() { - return this.$wwEditorContainerEl; - } - }]); - - return Layout; -}(); - -exports.default = Layout; - -/***/ }), -/* 84 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview Implements Command - * @author NHN FE Development Lab - */ - - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Class Command - * @param {string} name Command name - * @param {number} type Command type (Command.TYPE) - * @param {Array.} [keyMap] keyMap - * @ignore - */ -var Command = function () { - function Command(name, type, keyMap) { - _classCallCheck(this, Command); - - this.name = name; - this.type = type; - - if (keyMap) { - this.setKeyMap(keyMap); - } - } - - /** - * returns Name of command - * @returns {string} Command Name - */ - - - _createClass(Command, [{ - key: 'getName', - value: function getName() { - return this.name; - } - - /** - * returns Type of command - * @returns {number} Command Command type number - */ - - }, { - key: 'getType', - value: function getType() { - return this.type; - } - - /** - * returns whether Command Type is Markdown or not - * @returns {boolean} result - */ - - }, { - key: 'isMDType', - value: function isMDType() { - return this.type === Command.TYPE.MD; - } - - /** - * returns whether Command Type is Wysiwyg or not - * @returns {boolean} result - */ - - }, { - key: 'isWWType', - value: function isWWType() { - return this.type === Command.TYPE.WW; - } - - /** - * returns whether Command Type is Global or not - * @returns {boolean} result - */ - - }, { - key: 'isGlobalType', - value: function isGlobalType() { - return this.type === Command.TYPE.GB; - } - - /** - * Set keymap value for each os - * @param {string} win Windows Key(and etc) - * @param {string} mac Mac osx key - */ - - }, { - key: 'setKeyMap', - value: function setKeyMap(win, mac) { - this.keyMap = [win, mac]; - } - }]); - - return Command; -}(); - -/** - * Command factory method - * @param {string} typeStr Editor type name - * @param {object} props Property - * @param {string} props.name Command name - * @param {number} props.type Command type number - * @returns {Command} - * @static - */ - - -Command.factory = function (typeStr, props) { - var type = void 0; - - if (typeStr === 'markdown') { - type = Command.TYPE.MD; - } else if (typeStr === 'wysiwyg') { - type = Command.TYPE.WW; - } else if (typeStr === 'global') { - type = Command.TYPE.GB; - } - - var command = new Command(props.name, type); - - _tuiCodeSnippet2.default.extend(command, props); - - return command; -}; - -/** - * Command Type Constant - * markdown : 0 - * wysiwyg : 1 - * global : 2 - * @type {object} - * @private - */ -Command.TYPE = { - MD: 0, - WW: 1, - GB: 2 -}; - -exports.default = Command; - -/***/ }), -/* 85 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE__85__; - -/***/ }), -/* 86 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -// Copyright (c) 2016, Revin Guillen. -// Distributed under an MIT license: https://github.com/revin/markdown-it-task-lists/ - -/** - * @fileoverview Implements markdownitTaskPlugin - * @modifier Sungho Kim(sungho-kim@nhn.com) FE Development Lab/NHN - * @modifier Junghwan Park(junghwan.park@nhn.com) FE Development Lab/NHN - */ -/* eslint-disable */ - -/** - * Task list renderer for Markdown-it - * @param {object} markdownit Markdown-it instance - * @ignore - */ -var MarkdownitTaskRenderer = function MarkdownitTaskRenderer(markdownit) { - markdownit.core.ruler.after('inline', 'tui-task-list', function (state) { - var TASK_LIST_ITEM_CLASS_NAME = 'task-list-item'; - var CHECKED_CLASS_NAME = 'checked'; - var tokens = state.tokens; - var className; - var tokenIndex; - - // tokenIndex=0 'ul', tokenIndex=1 'li', tokenIndex=2 'p_open' - for (tokenIndex = 2; tokenIndex < tokens.length; tokenIndex += 1) { - if (isTaskListItemToken(tokens, tokenIndex)) { - if (isChecked(tokens[tokenIndex])) { - className = TASK_LIST_ITEM_CLASS_NAME + ' ' + CHECKED_CLASS_NAME; - } else { - className = TASK_LIST_ITEM_CLASS_NAME; - } - - removeMarkdownTaskFormatText(tokens[tokenIndex]); - - setTokenAttribute(tokens[tokenIndex - 2], 'class', className); - setTokenAttribute(tokens[tokenIndex - 2], 'data-te-task', ''); - } - } - }); -}; - -/** - * Remove task format text for rendering - * @param {object} token Token object - * @ignore - */ -function removeMarkdownTaskFormatText(token) { - // '[X] ' length is 4 - // FIXED: we don't need first space - token.content = token.content.slice(4); - token.children[0].content = token.children[0].content.slice(4); -} - -/** - * Return boolean value whether task checked or not - * @param {object} token Token object - * @returns {boolean} - * @ignore - */ -function isChecked(token) { - var checked = false; - - if (token.content.indexOf('[x]') === 0 || token.content.indexOf('[X]') === 0) { - checked = true; - } - - return checked; -} - -/** - * Set attribute of passed token - * @param {object} token Token object - * @param {string} attributeName Attribute name for set - * @param {string} attributeValue Attribute value for set - * @ignore - */ -function setTokenAttribute(token, attributeName, attributeValue) { - var index = token.attrIndex(attributeName); - var attr = [attributeName, attributeValue]; - - if (index < 0) { - token.attrPush(attr); - } else { - token.attrs[index] = attr; - } -} - -/** - * Return boolean value whether task list item or not - * @param {array} tokens Token object - * @param {number} index Number of token index - * @returns {boolean} - * @ignore - */ -function isTaskListItemToken(tokens, index) { - return tokens[index].type === 'inline' && tokens[index - 1].type === 'paragraph_open' && tokens[index - 2].type === 'list_item_open' && (tokens[index].content.indexOf('[ ]') === 0 || tokens[index].content.indexOf('[x]') === 0 || tokens[index].content.indexOf('[X]') === 0); -} -/* eslint-enable */ - -module.exports = MarkdownitTaskRenderer; - -/***/ }), -/* 87 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -// Copyright (c) 2016, Revin Guillen. -// Distributed under an MIT license: https://github.com/revin/markdown-it-task-lists/ -/* eslint-disable */ -/** - * @fileoverview Implements markdownitCodeBlockPlugin - * @modifier NHN FE Development Lab - */ - -/** - * Code block renderer for Markdown-it - * @param {object} markdownit Markdown-it instance - * @ignore - */ -var MarkdownitCodeBlockRenderer = function MarkdownitCodeBlockRenderer(markdownit) { - markdownit.core.ruler.after('block', 'tui-code-block', function (state) { - var DEFAULT_NUMBER_OF_BACKTICKS = 3; - var tokens = state.tokens; - var currentToken, tokenIndex, numberOfBackticks; - - for (tokenIndex = 0; tokenIndex < tokens.length; tokenIndex += 1) { - currentToken = tokens[tokenIndex]; - - if (isCodeFenceToken(currentToken)) { - numberOfBackticks = currentToken.markup.length; - if (numberOfBackticks > DEFAULT_NUMBER_OF_BACKTICKS) { - setTokenAttribute(currentToken, 'data-backticks', numberOfBackticks, true); - } - if (currentToken.info) { - setTokenAttribute(currentToken, 'data-language', escape(currentToken.info.replace(' ', ''), true)); - } - } - } - }); -}; - -/** - * Set attribute of passed token - * @param {object} token Token object - * @param {string} attributeName Attribute name for set - * @param {string} attributeValue Attribute value for set - * @ignore - */ -function setTokenAttribute(token, attributeName, attributeValue) { - var index = token.attrIndex(attributeName); - var attr = [attributeName, attributeValue]; - - if (index < 0) { - token.attrPush(attr); - } else { - token.attrs[index] = attr; - } -} -/** - * Return boolean value whether passed token is code fence or not - * @param {object} token Token object - * @returns {boolean} - * @ignore - */ -function isCodeFenceToken(token) { - return token.block === true && token.tag === 'code' && token.type === 'fence'; -} - -/** - * escape code from markdown-it - * @param {string} html HTML string - * @param {string} encode Boolean value of whether encode or not - * @returns {string} - * @ignore - */ -function escape(html, encode) { - return html.replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, '''); -} -/* eslint-enable */ - -module.exports = MarkdownitCodeBlockRenderer; - -/***/ }), -/* 88 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -// Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin. -// Distributed under an ISC license: https://github.com/markdown-it/markdown-it/ -/** - * @fileoverview Implements MarkdownItCodeRenderer - * @modifier NHN FE Development Lab - */ - -/* eslint-disable */ -module.exports = function code(state, startLine, endLine /*, silent*/) { - // Added by Junghwan Park - var FIND_LIST_RX = / {0,3}(?:-|\*|\d\.) /; - var lines = state.src.split('\n'); - var currentLine = lines[startLine]; - // Added by Junghwan Park - - var nextLine, - last, - token, - emptyLines = 0; - - // Add condition by Junghwan Park - if (currentLine.match(FIND_LIST_RX) || state.sCount[startLine] - state.blkIndent < 4) { - // Add condition by Junghwan Park - return false; - } - - last = nextLine = startLine + 1; - - while (nextLine < endLine) { - if (state.isEmpty(nextLine)) { - emptyLines++; - - // workaround for lists: 2 blank lines should terminate indented - // code block, but not fenced code block - if (emptyLines >= 2 && state.parentType === 'list') { - break; - } - - nextLine++; - continue; - } - - emptyLines = 0; - - if (state.sCount[nextLine] - state.blkIndent >= 4) { - nextLine++; - last = nextLine; - continue; - } - break; - } - - state.line = last; - - token = state.push('code_block', 'code', 0); - token.content = state.getLines(startLine, last, 4 + state.blkIndent, true); - token.map = [startLine, state.line]; - - return true; -}; -/* eslint-enable */ - -/***/ }), -/* 89 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -// Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin. -// Distributed under MIT license: https://github.com/markdown-it/markdown-it/ -/** - * @fileoverview Implements markdownitCodeBlockQuoteRenderer - * @modifier NHN FE Development Lab - */ - -/* eslint-disable */ - -// Block quotes - - - -// prevent quote, pre in list #811 -// ref: #989 -// #811 START -// var isSpace = require('../common/utils').isSpace; - -function isSpace(code) { - switch (code) { - case 0x09: - case 0x20: - return true; - } - return false; -} -// #811 END - -module.exports = function blockquote(state, startLine, endLine, silent) { - var adjustTab, - ch, - i, - initial, - l, - lastLineEmpty, - lines, - nextLine, - offset, - oldBMarks, - oldBSCount, - oldIndent, - oldParentType, - oldSCount, - oldTShift, - spaceAfterMarker, - terminate, - terminatorRules, - token, - wasOutdented, - oldLineMax = state.lineMax, - pos = state.bMarks[startLine] + state.tShift[startLine], - max = state.eMarks[startLine]; - - // #811 START - var FIND_LIST_RX = /(?:-|\*|\d+\.) {1,4}(?:> {0,3})[^>]*$/; - var sourceLines = state.src.split('\n'); - var currentLine = sourceLines[startLine]; - // #811 END - - // if it's indented more than 3 spaces, it should be a code block - if (state.sCount[startLine] - state.blkIndent >= 4) { - return false; - } - - // check the block quote marker - if (state.src.charCodeAt(pos++) !== 0x3E /* > */) { - return false; - } - // #811 START - // check block quote in list - if (currentLine.match(FIND_LIST_RX) /*&& !currentLine.match(/^ {0,6}>/)*/) { - return false; - } - // #811 END - - // we know that it's going to be a valid blockquote, - // so no point trying to find the end of it in silent mode - if (silent) { - return true; - } - - // skip spaces after ">" and re-calculate offset - initial = offset = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[startLine]); - - // skip one optional space after '>' - if (state.src.charCodeAt(pos) === 0x20 /* space */) { - // ' > test ' - // ^ -- position start of line here: - pos++; - initial++; - offset++; - adjustTab = false; - spaceAfterMarker = true; - } else if (state.src.charCodeAt(pos) === 0x09 /* tab */) { - spaceAfterMarker = true; - - if ((state.bsCount[startLine] + offset) % 4 === 3) { - // ' >\t test ' - // ^ -- position start of line here (tab has width===1) - pos++; - initial++; - offset++; - adjustTab = false; - } else { - // ' >\t test ' - // ^ -- position start of line here + shift bsCount slightly - // to make extra space appear - adjustTab = true; - } - } else { - spaceAfterMarker = false; - } - - oldBMarks = [state.bMarks[startLine]]; - state.bMarks[startLine] = pos; - - while (pos < max) { - ch = state.src.charCodeAt(pos); - - if (isSpace(ch)) { - if (ch === 0x09) { - offset += 4 - (offset + state.bsCount[startLine] + (adjustTab ? 1 : 0)) % 4; - } else { - offset++; - } - } else { - break; - } - - pos++; - } - - oldBSCount = [state.bsCount[startLine]]; - state.bsCount[startLine] = state.sCount[startLine] + 1 + (spaceAfterMarker ? 1 : 0); - - lastLineEmpty = pos >= max; - - oldSCount = [state.sCount[startLine]]; - state.sCount[startLine] = offset - initial; - - oldTShift = [state.tShift[startLine]]; - state.tShift[startLine] = pos - state.bMarks[startLine]; - - terminatorRules = state.md.block.ruler.getRules('blockquote'); - - oldParentType = state.parentType; - state.parentType = 'blockquote'; - wasOutdented = false; - - // Search the end of the block - // - // Block ends with either: - // 1. an empty line outside: - // ``` - // > test - // - // ``` - // 2. an empty line inside: - // ``` - // > - // test - // ``` - // 3. another tag: - // ``` - // > test - // - - - - // ``` - for (nextLine = startLine + 1; nextLine < endLine; nextLine++) { - // check if it's outdented, i.e. it's inside list item and indented - // less than said list item: - // - // ``` - // 1. anything - // > current blockquote - // 2. checking this line - // ``` - if (state.sCount[nextLine] < state.blkIndent) wasOutdented = true; - - pos = state.bMarks[nextLine] + state.tShift[nextLine]; - max = state.eMarks[nextLine]; - - if (pos >= max) { - // Case 1: line is not inside the blockquote, and this line is empty. - break; - } - - if (state.src.charCodeAt(pos++) === 0x3E /* > */ && !wasOutdented) { - // This line is inside the blockquote. - - // skip spaces after ">" and re-calculate offset - initial = offset = state.sCount[nextLine] + pos - (state.bMarks[nextLine] + state.tShift[nextLine]); - - // skip one optional space after '>' - if (state.src.charCodeAt(pos) === 0x20 /* space */) { - // ' > test ' - // ^ -- position start of line here: - pos++; - initial++; - offset++; - adjustTab = false; - spaceAfterMarker = true; - } else if (state.src.charCodeAt(pos) === 0x09 /* tab */) { - spaceAfterMarker = true; - - if ((state.bsCount[nextLine] + offset) % 4 === 3) { - // ' >\t test ' - // ^ -- position start of line here (tab has width===1) - pos++; - initial++; - offset++; - adjustTab = false; - } else { - // ' >\t test ' - // ^ -- position start of line here + shift bsCount slightly - // to make extra space appear - adjustTab = true; - } - } else { - spaceAfterMarker = false; - } - - oldBMarks.push(state.bMarks[nextLine]); - state.bMarks[nextLine] = pos; - - while (pos < max) { - ch = state.src.charCodeAt(pos); - - if (isSpace(ch)) { - if (ch === 0x09) { - offset += 4 - (offset + state.bsCount[nextLine] + (adjustTab ? 1 : 0)) % 4; - } else { - offset++; - } - } else { - break; - } - - pos++; - } - - lastLineEmpty = pos >= max; - - oldBSCount.push(state.bsCount[nextLine]); - state.bsCount[nextLine] = state.sCount[nextLine] + 1 + (spaceAfterMarker ? 1 : 0); - - oldSCount.push(state.sCount[nextLine]); - state.sCount[nextLine] = offset - initial; - - oldTShift.push(state.tShift[nextLine]); - state.tShift[nextLine] = pos - state.bMarks[nextLine]; - continue; - } - - // Case 2: line is not inside the blockquote, and the last line was empty. - if (lastLineEmpty) { - break; - } - - // Case 3: another tag found. - terminate = false; - for (i = 0, l = terminatorRules.length; i < l; i++) { - if (terminatorRules[i](state, nextLine, endLine, true)) { - terminate = true; - break; - } - } - - if (terminate) { - // Quirk to enforce "hard termination mode" for paragraphs; - // normally if you call `tokenize(state, startLine, nextLine)`, - // paragraphs will look below nextLine for paragraph continuation, - // but if blockquote is terminated by another tag, they shouldn't - state.lineMax = nextLine; - - if (state.blkIndent !== 0) { - // state.blkIndent was non-zero, we now set it to zero, - // so we need to re-calculate all offsets to appear as - // if indent wasn't changed - oldBMarks.push(state.bMarks[nextLine]); - oldBSCount.push(state.bsCount[nextLine]); - oldTShift.push(state.tShift[nextLine]); - oldSCount.push(state.sCount[nextLine]); - state.sCount[nextLine] -= state.blkIndent; - } - - break; - } - - oldBMarks.push(state.bMarks[nextLine]); - oldBSCount.push(state.bsCount[nextLine]); - oldTShift.push(state.tShift[nextLine]); - oldSCount.push(state.sCount[nextLine]); - - // A negative indentation means that this is a paragraph continuation - // - state.sCount[nextLine] = -1; - } - - oldIndent = state.blkIndent; - state.blkIndent = 0; - - token = state.push('blockquote_open', 'blockquote', 1); - token.markup = '>'; - token.map = lines = [startLine, 0]; - - state.md.block.tokenize(state, startLine, nextLine); - - token = state.push('blockquote_close', 'blockquote', -1); - token.markup = '>'; - - state.lineMax = oldLineMax; - state.parentType = oldParentType; - lines[1] = state.line; - - // Restore original tShift; this might not be necessary since the parser - // has already been here, but just to make sure we can do that. - for (i = 0; i < oldTShift.length; i++) { - state.bMarks[i + startLine] = oldBMarks[i]; - state.tShift[i + startLine] = oldTShift[i]; - state.sCount[i + startLine] = oldSCount[i]; - state.bsCount[i + startLine] = oldBSCount[i]; - } - state.blkIndent = oldIndent; - - return true; -}; - -/***/ }), -/* 90 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -// Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin. -// Distributed under an ISC license: https://github.com/markdown-it/markdown-it/ - -/** - * @fileoverview Implements markdownitTableRenderer - * @modifier NHN FE Development Lab - */ - -/*eslint-disable */ -function getLine(state, line) { - var pos = state.bMarks[line] + state.blkIndent, - max = state.eMarks[line]; - - return state.src.substr(pos, max - pos); -} - -function escapedSplit(str) { - var result = [], - pos = 0, - max = str.length, - ch, - escapes = 0, - lastPos = 0, - backTicked = false, - lastBackTick = 0; - - ch = str.charCodeAt(pos); - - while (pos < max) { - if (ch === 0x60 /* ` */ && escapes % 2 === 0) { - backTicked = !backTicked; - lastBackTick = pos; - } else if (ch === 0x7c /* | */ && escapes % 2 === 0 && !backTicked) { - result.push(str.substring(lastPos, pos)); - lastPos = pos + 1; - } else if (ch === 0x5c /* \ */) { - escapes += 1; - } else { - escapes = 0; - } - - pos += 1; - - // If there was an un-closed backtick, go back to just after - // the last backtick, but as if it was a normal character - if (pos === max && backTicked) { - backTicked = false; - pos = lastBackTick + 1; - } - - ch = str.charCodeAt(pos); - } - - result.push(str.substring(lastPos)); - - return result; -} - -module.exports = function table(state, startLine, endLine, silent) { - var ch, lineText, pos, i, nextLine, columns, columnCount, token, aligns, alignCount, t, tableLines, tbodyLines; - - // should have at least three lines - if (startLine + 2 > endLine) { - return false; - } - - nextLine = startLine + 1; - - if (state.sCount[nextLine] < state.blkIndent) { - return false; - } - - // first character of the second line should be '|' or '-' - - pos = state.bMarks[nextLine] + state.tShift[nextLine]; - if (pos >= state.eMarks[nextLine]) { - return false; - } - - ch = state.src.charCodeAt(pos); - if (ch !== 0x7C /* | */ && ch !== 0x2D /* - */ && ch !== 0x3A /* : */) { - return false; - } - - lineText = getLine(state, startLine + 1); - if (!/^[-:| ]+$/.test(lineText)) { - return false; - } - - columns = lineText.split('|'); - aligns = []; - for (i = 0; i < columns.length; i += 1) { - t = columns[i].trim(); - if (!t) { - // allow empty columns before and after table, but not in between columns; - // e.g. allow ` |---| `, disallow ` ---||--- ` - if (i === 0 || i === columns.length - 1) { - continue; - } else { - return false; - } - } - - if (!/^:?-+:?$/.test(t)) { - return false; - } - if (t.charCodeAt(t.length - 1) === 0x3A /* : */) { - aligns.push(t.charCodeAt(0) === 0x3A /* : */ ? 'center' : 'right'); - } else if (t.charCodeAt(0) === 0x3A /* : */) { - aligns.push('left'); - } else { - aligns.push(''); - } - } - alignCount = aligns.length; - - lineText = getLine(state, startLine).trim(); - if (lineText.indexOf('|') === -1) { - return false; - } - columns = escapedSplit(lineText.replace(/^\||\|$/g, '')); - - // header row will define an amount of columns in the entire table, - // and align row shouldn't be smaller than that (the rest of the rows can) - columnCount = columns.length; - if (columnCount > alignCount) { - return false; - } else if (columnCount < alignCount) { - for (i = 0; i < alignCount - columnCount; i += 1) { - columns.push(''); - } - columnCount = columns.length; - } - - if (silent) { - return true; - } - - token = state.push('table_open', 'table', 1); - token.map = tableLines = [startLine, 0]; - - token = state.push('thead_open', 'thead', 1); - token.map = [startLine, startLine + 1]; - - token = state.push('tr_open', 'tr', 1); - token.map = [startLine, startLine + 1]; - - for (i = 0; i < columnCount; i += 1) { - token = state.push('th_open', 'th', 1); - token.map = [startLine, startLine + 1]; - if (aligns[i]) { - // FIXED: change property style to align - token.attrs = [['align', aligns[i]]]; - } - - token = state.push('inline', '', 0); - token.content = columns[i].trim(); - token.map = [startLine, startLine + 1]; - token.children = []; - - token = state.push('th_close', 'th', -1); - } - - token = state.push('tr_close', 'tr', -1); - token = state.push('thead_close', 'thead', -1); - - token = state.push('tbody_open', 'tbody', 1); - token.map = tbodyLines = [startLine + 2, 0]; - - for (nextLine = startLine + 2; nextLine < endLine; nextLine += 1) { - if (state.sCount[nextLine] < state.blkIndent) { - break; - } - - lineText = getLine(state, nextLine); - if (lineText.indexOf('|') === -1) { - break; - } - - // keep spaces at beginning of line to indicate an empty first cell, but - // strip trailing whitespace - columns = escapedSplit(lineText.replace(/^\||\|\s*$/g, '')); - - token = state.push('tr_open', 'tr', 1); - for (i = 0; i < columnCount; i += 1) { - token = state.push('td_open', 'td', 1); - if (aligns[i]) { - // FIXED: change property style to align - token.attrs = [['align', aligns[i]]]; - } - - token = state.push('inline', '', 0); - token.content = columns[i] ? columns[i].trim() : ''; - token.children = []; - - token = state.push('td_close', 'td', -1); - } - token = state.push('tr_close', 'tr', -1); - } - token = state.push('tbody_close', 'tbody', -1); - token = state.push('table_close', 'table', -1); - - tableLines[1] = tbodyLines[1] = nextLine; - state.line = nextLine; - return true; -}; - -/***/ }), -/* 91 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -// Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin. -// Distributed under an ISC license: https://github.com/markdown-it/markdown-it/ - -/** - * @fileoverview Implements markdownitHtmlBlockRenderer - * @modifier NHN FE Development Lab - */ -/* eslint-disable */ -// HTML block - - - -// An array of opening and corresponding closing sequences for html tags, -// last argument defines whether it can terminate a paragraph or not -// - -// void tag names --- Added by Junghwan Park - -var voidTagNames = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']; -var HTML_SEQUENCES = [[/^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true], [/^/, true], [/^<\?/, /\?>/, true], [/^/, true], [/^/, true], [new RegExp('^<(' + voidTagNames.join('|') + ')', 'i'), /^\/?>$/, true], [new RegExp('^|$))', 'i'), /^$/, true], [/^(?:<[A-Za-z][A-Za-z0-9\-]*(?:\s+[a-zA-Z_:][a-zA-Z0-9:._-]*(?:\s*=\s*(?:[^"'=<>`\x00-\x20]+|'[^']*'|"[^"]*"))?)*\s*\/?>|<\/[A-Za-z][A-Za-z0-9\-]*\s*>)\s*$/, /^$/, false]]; - -module.exports = function html_block(state, startLine, endLine, silent) { - var i, - nextLine, - token, - lineText, - pos = state.bMarks[startLine] + state.tShift[startLine], - max = state.eMarks[startLine]; - - if (!state.md.options.html) { - return false; - } - - if (state.src.charCodeAt(pos) !== 0x3C /* < */) { - return false; - } - - lineText = state.src.slice(pos, max); - - for (i = 0; i < HTML_SEQUENCES.length; i++) { - if (HTML_SEQUENCES[i][0].test(lineText)) { - // add condition for return when meet void element --- Added by Junghwan Park - if (i === 5) { - return false; - } else { - break; - } - } - } - - if (i === HTML_SEQUENCES.length) { - return false; - } - - if (silent) { - // true if this sequence can be a terminator, false otherwise - return HTML_SEQUENCES[i][2]; - } - - nextLine = startLine + 1; - - // If we are here - we detected HTML block. - // Let's roll down till block end. - if (!HTML_SEQUENCES[i][1].test(lineText)) { - for (; nextLine < endLine; nextLine++) { - if (state.sCount[nextLine] < state.blkIndent) { - break; - } - - pos = state.bMarks[nextLine] + state.tShift[nextLine]; - max = state.eMarks[nextLine]; - lineText = state.src.slice(pos, max); - - if (HTML_SEQUENCES[i][1].test(lineText)) { - if (lineText.length !== 0) { - nextLine++; - } - break; - } - } - } - - state.line = nextLine; - - token = state.push('html_block', '', 0); - token.map = [startLine, nextLine]; - token.content = state.getLines(startLine, nextLine, state.blkIndent, true); - - return true; -}; -/* eslint-enable */ - -/***/ }), -/* 92 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -// Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin. -// Distributed under MIT license: https://github.com/markdown-it/markdown-it/ -/** - * @fileoverview Implements markdownitBackticksRenderer - * @modifier NHN FE Development Lab - */ -/* eslint-disable */ - -// Parse backticks -module.exports = function backtick(state, silent) { - var start, - max, - marker, - matchStart, - matchEnd, - token, - pos = state.pos, - ch = state.src.charCodeAt(pos); - - if (ch !== 0x60 /* ` */) { - return false; - } - - start = pos; - pos++; - max = state.posMax; - - while (pos < max && state.src.charCodeAt(pos) === 0x60 /* ` */) { - pos++; - } - - marker = state.src.slice(start, pos); - - matchStart = matchEnd = pos; - - while ((matchStart = state.src.indexOf('`', matchEnd)) !== -1) { - matchEnd = matchStart + 1; - - while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60 /* ` */) { - matchEnd++; - } - - if (matchEnd - matchStart === marker.length) { - if (!silent) { - token = state.push('code_inline', 'code', 0); - token.markup = marker; - token.content = state.src.slice(pos, matchStart).replace(/[ \n]+/g, ' ').trim(); - // TUI.EDITOR MODIFICATION START - // store number of backtick in data-backtick - // https://github.nhn.com/fe/tui.editor/pull/981 - token.attrSet('data-backticks', token.markup.length); - // TUI.EDITOR MODIFICATION END - } - state.pos = matchEnd; - return true; - } - } - - if (!silent) { - state.pending += marker; - } - state.pos += marker.length; - return true; -}; - -/***/ }), -/* 93 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -// Copyright (c) 2014, Vitaly Puzrin. -// Distributed under an MIT license: https://github.com/markdown-it/markdown-it-for-inline -/* eslint-disable */ - -/** - * @fileoverview Implements markdownItLinkPlugin - * @modifier NHN FE Development Lab - */ - -function for_inline_plugin(md, ruleName, tokenType, iteartor) { - - function scan(state) { - var i, blkIdx, inlineTokens; - - for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) { - if (state.tokens[blkIdx].type !== 'inline') { - continue; - } - - inlineTokens = state.tokens[blkIdx].children; - - for (i = inlineTokens.length - 1; i >= 0; i--) { - if (inlineTokens[i].type !== tokenType) { - continue; - } - - iteartor(inlineTokens, i); - } - } - } - - md.core.ruler.push(ruleName, scan); -}; - -var linkAttribute = exports.linkAttribute = function linkAttribute(markdownit, iteartor) { - for_inline_plugin(markdownit, 'url_attribute', 'link_open', iteartor); -}; - -/***/ }), -/* 94 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE__94__; - -/***/ }), -/* 95 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview Implements editor preivew - * @author NHN FE Development Lab - */ - - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _mdPreview = __webpack_require__(34); - -var _mdPreview2 = _interopRequireDefault(_mdPreview); - -var _eventManager = __webpack_require__(40); - -var _eventManager2 = _interopRequireDefault(_eventManager); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _extManager = __webpack_require__(41); - -var _extManager2 = _interopRequireDefault(_extManager); - -var _convertor = __webpack_require__(42); - -var _convertor2 = _interopRequireDefault(_convertor); - -var _domUtils = __webpack_require__(4); - -var _domUtils2 = _interopRequireDefault(_domUtils); - -var _codeBlockManager = __webpack_require__(25); - -var _codeBlockManager2 = _interopRequireDefault(_codeBlockManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var TASK_ATTR_NAME = 'data-te-task'; -var TASK_CHECKED_CLASS_NAME = 'checked'; - -/** - * Class ToastUIEditorViewer - * @param {object} options Option object - * @param {HTMLElement} options.el - container element - * @param {string} options.initialValue Editor's initial value - * @param {object} options.events eventlist Event list - * @param {function} options.events.load It would be emitted when editor fully load - * @param {function} options.events.change It would be emitted when content changed - * @param {function} options.events.stateChange It would be emitted when format change by cursor position - * @param {function} options.events.focus It would be emitted when editor get focus - * @param {function} options.events.blur It would be emitted when editor loose focus - * @param {object} options.hooks Hook list - * @param {function} options.hooks.previewBeforeHook Submit preview to hook URL before preview be shown - * @param {string[]} [options.exts] - extensions - */ - -var ToastUIEditorViewer = function () { - function ToastUIEditorViewer(options) { - var _this = this; - - _classCallCheck(this, ToastUIEditorViewer); - - this.options = _jquery2.default.extend({ - useDefaultHTMLSanitizer: true, - codeBlockLanguages: _codeBlockManager.CodeBlockManager.getHighlightJSLanguages(), - customConvertor: null - }, options); - - this.eventManager = new _eventManager2.default(); - this.commandManager = new _commandManager2.default(this); - if (this.options.customConvertor) { - // eslint-disable-next-line new-cap - this.convertor = new this.options.customConvertor(this.eventManager); - } else { - this.convertor = new _convertor2.default(this.eventManager); - } - - if (this.options.useDefaultHTMLSanitizer) { - this.convertor.initHtmlSanitizer(); - } - - if (this.options.hooks) { - _tuiCodeSnippet2.default.forEach(this.options.hooks, function (fn, key) { - _this.addHook(key, fn); - }); - } - - if (this.options.events) { - _tuiCodeSnippet2.default.forEach(this.options.events, function (fn, key) { - _this.on(key, fn); - }); - } - - var _options = this.options, - el = _options.el, - initialValue = _options.initialValue; - - var existingHTML = el.innerHTML; - el.innerHTML = ''; - - this.preview = new _mdPreview2.default((0, _jquery2.default)(el), this.eventManager, this.convertor, true); - - this.preview.$el.on('mousedown', _jquery2.default.proxy(this._toggleTask, this)); - - _extManager2.default.applyExtension(this, this.options.exts); - - if (initialValue) { - this.setValue(initialValue); - } else if (existingHTML) { - this.preview.setHTML(existingHTML); - } - - this.eventManager.emit('load', this); - } - - /** - * Toggle task by detecting mousedown event. - * @param {MouseEvent} ev - event - * @private - */ - - - _createClass(ToastUIEditorViewer, [{ - key: '_toggleTask', - value: function _toggleTask(ev) { - var style = getComputedStyle(ev.target, ':before'); - - if (ev.target.hasAttribute(TASK_ATTR_NAME) && _domUtils2.default.isInsideTaskBox(style, ev.offsetX, ev.offsetY)) { - (0, _jquery2.default)(ev.target).toggleClass(TASK_CHECKED_CLASS_NAME); - this.eventManager.emit('change', { - source: 'viewer', - data: ev - }); - } - } - - /** - * Set content for preview - * @param {string} markdown Markdown text - */ - - }, { - key: 'setMarkdown', - value: function setMarkdown(markdown) { - this.markdownValue = markdown = markdown || ''; - - this.preview.refresh(this.markdownValue); - this.eventManager.emit('setMarkdownAfter', this.markdownValue); - } - - /** - * Set content for preview - * @param {string} markdown Markdown text - * @deprecated - */ - - }, { - key: 'setValue', - value: function setValue(markdown) { - this.setMarkdown(markdown); - } - - /** - * Bind eventHandler to event type - * @param {string} type Event type - * @param {function} handler Event handler - */ - - }, { - key: 'on', - value: function on(type, handler) { - this.eventManager.listen(type, handler); - } - - /** - * Unbind eventHandler from event type - * @param {string} type Event type - */ - - }, { - key: 'off', - value: function off(type) { - this.eventManager.removeEventHandler(type); - } - - /** - * Remove Viewer preview from document - */ - - }, { - key: 'remove', - value: function remove() { - this.eventManager.emit('removeEditor'); - this.preview.$el.off('mousedown', _jquery2.default.proxy(this._toggleTask, this)); - this.preview.remove(); - this.options = null; - this.eventManager = null; - this.commandManager = null; - this.convertor = null; - this.preview = null; - } - - /** - * Add hook to Viewer preview's event - * @param {string} type Event type - * @param {function} handler Event handler - */ - - }, { - key: 'addHook', - value: function addHook(type, handler) { - this.eventManager.removeEventHandler(type); - this.eventManager.listen(type, handler); - } - - /** - * Return true - * @returns {boolean} - */ - - }, { - key: 'isViewer', - value: function isViewer() { - return true; - } - - /** - * Return false - * @returns {boolean} - */ - - }, { - key: 'isMarkdownMode', - value: function isMarkdownMode() { - return false; - } - - /** - * Return false - * @returns {boolean} - */ - - }, { - key: 'isWysiwygMode', - value: function isWysiwygMode() { - return false; - } - - /** - * Define extension - * @param {string} name Extension name - * @param {ExtManager~extension} ext extension - */ - - }], [{ - key: 'defineExtension', - value: function defineExtension(name, ext) { - _extManager2.default.defineExtension(name, ext); - } - }]); - - return ToastUIEditorViewer; -}(); - -/** - * check whther is viewer - * @type {boolean} - */ - - -ToastUIEditorViewer.isViewer = true; - -/** - * domUtil instance - * @type {DomUtil} - * @ignore - */ -ToastUIEditorViewer.domUtils = _domUtils2.default; - -/** - * CodeBlockManager instance - * @type {CodeBlockManager} - */ -ToastUIEditorViewer.codeBlockManager = _codeBlockManager2.default; - -/** - * MarkdownIt hightlight instance - * @type {MarkdownIt} - */ -ToastUIEditorViewer.markdownitHighlight = _convertor2.default.getMarkdownitHighlightRenderer(); - -/** - * MarkdownIt instance - * @type {MarkdownIt} - */ -ToastUIEditorViewer.markdownit = _convertor2.default.getMarkdownitRenderer(); - -/** - * @ignore - */ -ToastUIEditorViewer.i18n = null; - -/** - * @ignore - */ -ToastUIEditorViewer.Button = null; - -/** - * @ignore - */ -ToastUIEditorViewer.WwCodeBlockManager = null; - -/** - * @ignore - */ -ToastUIEditorViewer.WwTableManager = null; - -/** - * @ignore - */ -ToastUIEditorViewer.WwTableSelectionManager = null; - -module.exports = ToastUIEditorViewer; - -/***/ }), -/* 96 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview default UI - * @author NHN FE Development Lab - */ - - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _defaultToolbar = __webpack_require__(97); - -var _defaultToolbar2 = _interopRequireDefault(_defaultToolbar); - -var _tab = __webpack_require__(46); - -var _tab2 = _interopRequireDefault(_tab); - -var _layerpopup = __webpack_require__(7); - -var _layerpopup2 = _interopRequireDefault(_layerpopup); - -var _modeSwitch = __webpack_require__(101); - -var _modeSwitch2 = _interopRequireDefault(_modeSwitch); - -var _popupAddLink = __webpack_require__(102); - -var _popupAddLink2 = _interopRequireDefault(_popupAddLink); - -var _popupAddImage = __webpack_require__(103); - -var _popupAddImage2 = _interopRequireDefault(_popupAddImage); - -var _popupTableUtils = __webpack_require__(104); - -var _popupTableUtils2 = _interopRequireDefault(_popupTableUtils); - -var _popupAddTable = __webpack_require__(105); - -var _popupAddTable2 = _interopRequireDefault(_popupAddTable); - -var _popupAddHeading = __webpack_require__(106); - -var _popupAddHeading2 = _interopRequireDefault(_popupAddHeading); - -var _popupCodeBlockLanguages = __webpack_require__(107); - -var _popupCodeBlockLanguages2 = _interopRequireDefault(_popupCodeBlockLanguages); - -var _popupCodeBlockEditor = __webpack_require__(108); - -var _popupCodeBlockEditor2 = _interopRequireDefault(_popupCodeBlockEditor); - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -var _tooltip = __webpack_require__(31); - -var _tooltip2 = _interopRequireDefault(_tooltip); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var CLASS_TOOLBAR = 'te-toolbar-section'; -var CLASS_MARKDOWN_TAB = 'te-markdown-tab-section'; -var CLASS_EDITOR = 'te-editor-section'; -var CLASS_MODE_SWITCH = 'te-mode-switch-section'; -var CONTAINER_TEMPLATE = '\n
    \n
    \n
    \n
    \n
    \n'; - -/** - * Class DefaultUI - * @param {ToastUIEditor} editor - editor instance - */ - -var DefaultUI = function () { - - /** - * mode switch instance - * @private - * @type {ModeSwitch} - */ - - - /** - * markdown tab section jQuery element - * @private - * @type {HTMLElement} - */ - - - /** - * editor type ww/md - * @private - * @type {string} - */ - - - /** - * @type {HTMLElement} - * @private - */ - - - /** - * DefaultToolbar wrapper element - * @type {jQuery} - */ - function DefaultUI(editor) { - _classCallCheck(this, DefaultUI); - - Object.defineProperty(this, 'name', { - enumerable: true, - writable: true, - value: 'default' - }); - Object.defineProperty(this, '_popups', { - enumerable: true, - writable: true, - value: [] - }); - - this._editor = editor; - this._initialEditType = editor.options.initialEditType; - - this._init(editor.options); - this._initEvent(); - } - - /** - * popup instances - * @private - * @type {Array} - */ - - - /** - * markdown tab - * @private - * @type {Tab} - */ - - - /** - * editor instance - * @private - * @type {ToastUIEditor} - */ - - - /** - * editor section element - * @private - * @type {HTMLElement} - */ - - - /** - * DefaultToolbar instance - * @type {DefaultToolbar} - * @private - */ - - /** - * UI name - * @type {string} - */ - - - _createClass(DefaultUI, [{ - key: '_init', - value: function _init(_ref) { - var container = _ref.el, - toolbarItems = _ref.toolbarItems, - hideModeSwitch = _ref.hideModeSwitch; - - this.$el = (0, _jquery2.default)(CONTAINER_TEMPLATE).appendTo(container); - this._container = container; - this._editorSection = this.$el.find('.' + CLASS_EDITOR).get(0); - this._editorSection.appendChild(this._editor.layout.getEditorEl().get(0)); - - this._initToolbar(this._editor.eventManager, toolbarItems); - this._initModeSwitch(hideModeSwitch); - - this._initPopupAddLink(); - this._initPopupAddImage(); - this._initPopupAddTable(); - this._initPopupAddHeading(); - this._initPopupTableUtils(); - this._initPopupCodeBlockLanguages(); - this._initPopupCodeBlockEditor(); - - this._initMarkdownTab(); - } - }, { - key: '_initEvent', - value: function _initEvent() { - this._editor.eventManager.listen('hide', this.hide.bind(this)); - this._editor.eventManager.listen('show', this.show.bind(this)); - this._editor.eventManager.listen('changeMode', this._markdownTabControl.bind(this)); - this._editor.eventManager.listen('changePreviewStyle', this._markdownTabControl.bind(this)); - } - }, { - key: '_initToolbar', - value: function _initToolbar(eventManager, toolbarItems) { - var toolbar = new _defaultToolbar2.default(eventManager, toolbarItems); - this._toolbar = toolbar; - this.$el.find('.' + CLASS_TOOLBAR).append(toolbar.$el); - } - }, { - key: '_initModeSwitch', - value: function _initModeSwitch(hideModeSwitch) { - var _this = this; - - var modeSwitchTabBar = this.$el.find('.' + CLASS_MODE_SWITCH); - var editType = this._initialEditType === 'markdown' ? _modeSwitch2.default.TYPE.MARKDOWN : _modeSwitch2.default.TYPE.WYSIWYG; - var modeSwitch = new _modeSwitch2.default(modeSwitchTabBar, editType); - this._modeSwitch = modeSwitch; - - if (hideModeSwitch) { - modeSwitch.hide(); - } - - modeSwitch.on('modeSwitched', function (ev, type) { - return _this._editor.changeMode(type); - }); - } - }, { - key: '_initMarkdownTab', - value: function _initMarkdownTab() { - var editor = this._editor; - - this._markdownTab = new _tab2.default({ - initName: _i18n2.default.get('Write'), - items: [_i18n2.default.get('Write'), _i18n2.default.get('Preview')], - sections: [editor.layout.getMdEditorContainerEl(), editor.layout.getPreviewEl()] - }); - this._$markdownTabSection = this.$el.find('.' + CLASS_MARKDOWN_TAB); - this._$markdownTabSection.append(this._markdownTab.$el); - - this._markdownTab.on('itemClick', function (ev, itemText) { - if (itemText === _i18n2.default.get('Preview')) { - editor.eventManager.emit('previewNeedsRefresh'); - editor.eventManager.emit('changePreviewTabPreview'); - editor.eventManager.emit('closeAllPopup'); - } else { - editor.getCodeMirror().focus(); - editor.eventManager.emit('changePreviewTabWrite'); - } - }); - } - }, { - key: '_markdownTabControl', - value: function _markdownTabControl() { - if (this._editor.isMarkdownMode() && this._editor.getCurrentPreviewStyle() === 'tab') { - this._$markdownTabSection.show(); - this._markdownTab.activate(_i18n2.default.get('Write')); - } else { - this._$markdownTabSection.hide(); - } - } - }, { - key: '_initPopupAddLink', - value: function _initPopupAddLink() { - this._popups.push(new _popupAddLink2.default({ - $target: this.$el, - editor: this._editor - })); - } - }, { - key: '_initPopupAddImage', - value: function _initPopupAddImage() { - this._popups.push(new _popupAddImage2.default({ - $target: this.$el, - eventManager: this._editor.eventManager - })); - } - }, { - key: '_initPopupAddTable', - value: function _initPopupAddTable() { - this._popups.push(new _popupAddTable2.default({ - $target: this._toolbar.$el, - eventManager: this._editor.eventManager, - $button: this.$el.find('button.tui-table'), - css: { - 'position': 'absolute' - } - })); - } - }, { - key: '_initPopupAddHeading', - value: function _initPopupAddHeading() { - this._popups.push(new _popupAddHeading2.default({ - $target: this._toolbar.$el, - eventManager: this._editor.eventManager, - $button: this.$el.find('button.tui-heading'), - css: { - 'position': 'absolute' - } - })); - } - }, { - key: '_initPopupTableUtils', - value: function _initPopupTableUtils() { - var _this2 = this; - - this._editor.eventManager.listen('contextmenu', function (ev) { - if ((0, _jquery2.default)(ev.data.target).parents('[contenteditable=true] table').length > 0) { - ev.data.preventDefault(); - _this2._editor.eventManager.emit('openPopupTableUtils', ev.data); - } - }); - - this._popups.push(new _popupTableUtils2.default({ - $target: this.$el, - eventManager: this._editor.eventManager - })); - } - }, { - key: '_initPopupCodeBlockLanguages', - value: function _initPopupCodeBlockLanguages() { - var editor = this._editor; - this._popups.push(new _popupCodeBlockLanguages2.default({ - $target: this.$el, - eventManager: editor.eventManager, - languages: editor.options.codeBlockLanguages - })); - } - }, { - key: '_initPopupCodeBlockEditor', - value: function _initPopupCodeBlockEditor() { - this._popups.push(new _popupCodeBlockEditor2.default({ - $target: this.$el, - eventManager: this._editor.eventManager, - convertor: this._editor.convertor - })); - } - - /** - * get toolbar instance - * @returns {Toolbar} - toolbar instance - */ - - }, { - key: 'getToolbar', - value: function getToolbar() { - return this._toolbar; - } - - /** - * set toolbar instance - * @param {Toolbar} toolbar - toolbar - */ - - }, { - key: 'setToolbar', - value: function setToolbar(toolbar) { - this._toolbar.destroy(); - this._toolbar = toolbar; - } - - /** - * get mode switch instance - * @returns {ModeSwitch} - mode switch instance - */ - - }, { - key: 'getModeSwitch', - value: function getModeSwitch() { - return this._modeSwitch; - } - - /** - * get editor section height - * @returns {Number} - height of editor section - */ - - }, { - key: 'getEditorSectionHeight', - value: function getEditorSectionHeight() { - var clientRect = this._editorSection.getBoundingClientRect(); - - return clientRect.bottom - clientRect.top; - } - - /** - * get editor height - * @returns {Number} - height of editor - */ - - }, { - key: 'getEditorHeight', - value: function getEditorHeight() { - var clientRect = this._container.getBoundingClientRect(); - - return clientRect.bottom - clientRect.top; - } - - /** - * get Table Popup - * @returns {PopupTableUtils} - PopupTableUtils - */ - - }, { - key: 'getPopupTableUtils', - value: function getPopupTableUtils() { - var tablePopup = void 0; - this._popups.forEach(function (popup) { - if (popup instanceof _popupTableUtils2.default) { - tablePopup = popup; - } - }); - - return tablePopup; - } - - /** - * hide - */ - - }, { - key: 'hide', - value: function hide() { - this.$el.addClass('te-hide'); - } - - /** - * show - */ - - }, { - key: 'show', - value: function show() { - this.$el.removeClass('te-hide'); - } - - /** - * remove - */ - - }, { - key: 'remove', - value: function remove() { - this.$el.remove(); - this._markdownTab.remove(); - this._modeSwitch.remove(); - this._toolbar.destroy(); - this._popups.forEach(function (popup) { - return popup.remove(); - }); - this._popups = []; - _tooltip2.default.hide(); - } - - /** - * creates popup - * @param {LayerPopupOption} options - layerPopup options - * @returns {LayerPopup} - crated layerPopup - */ - - }, { - key: 'createPopup', - value: function createPopup(options) { - return new _layerpopup2.default(options); - } - }]); - - return DefaultUI; -}(); - -exports.default = DefaultUI; - -/***/ }), -/* 97 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _resizeObserverPolyfill = __webpack_require__(98); - -var _resizeObserverPolyfill2 = _interopRequireDefault(_resizeObserverPolyfill); - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -var _toolbar = __webpack_require__(43); - -var _toolbar2 = _interopRequireDefault(_toolbar); - -var _popupDropdownToolbar = __webpack_require__(100); - -var _popupDropdownToolbar2 = _interopRequireDefault(_popupDropdownToolbar); - -var _toolbarItemFactory = __webpack_require__(45); - -var _toolbarItemFactory2 = _interopRequireDefault(_toolbarItemFactory); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview implements DefaultToolbar - * @author NHN FE Development Lab - */ - - -var MORE_BUTTON_NAME = 'more'; - -/** - * Class DefaultToolbar - */ - -var DefaultToolbar = function (_Toolbar) { - _inherits(DefaultToolbar, _Toolbar); - - /** - * popup dropdown toolbar - * @type {PopupDropdownToolbar} - * @private - */ - function DefaultToolbar(eventManager, options) { - _classCallCheck(this, DefaultToolbar); - - var _this = _possibleConstructorReturn(this, (DefaultToolbar.__proto__ || Object.getPrototypeOf(DefaultToolbar)).call(this, eventManager, options)); - - _this._init(eventManager); - _this._bindWidthChangedEvent(); - return _this; - } - - /** - * insert toolbar item - * @param {number} index - index at given item inserted - * @param {ToolbarItem|string|object} item - toolbar item - * @override - */ - - - /** - * resize observer - * @type {ResizeObserver} - * @private - */ - - /** - * more button - * @type {ToolbarButton} - * @private - */ - - - _createClass(DefaultToolbar, [{ - key: 'insertItem', - value: function insertItem(index, item) { - _get(DefaultToolbar.prototype.__proto__ || Object.getPrototypeOf(DefaultToolbar.prototype), 'insertItem', this).call(this, index, item); - this._arrangeMoreButton(); - } - }, { - key: '_init', - value: function _init(eventManager) { - var moreButton = _toolbarItemFactory2.default.create('button', { - name: MORE_BUTTON_NAME, - className: 'tui-more', - tooltip: _i18n2.default.get('More'), - event: _popupDropdownToolbar2.default.OPEN_EVENT - }); - this._moreButton = moreButton; - - this._popupDropdownToolbar = new _popupDropdownToolbar2.default({ - eventManager: eventManager, - $target: this.$el, - $button: moreButton.$el - }); - - this.addItem(moreButton); - } - }, { - key: '_bindWidthChangedEvent', - value: function _bindWidthChangedEvent() { - var _this2 = this; - - this._observer = new _resizeObserverPolyfill2.default(function () { - _this2._popupDropdownToolbar.hide(); - _this2._balanceButtons(); - }); - this._observer.observe(this.$el.get(0)); - } - }, { - key: '_balanceButtons', - value: function _balanceButtons() { - var _this3 = this; - - var dropDownToolbarItems = this._popupDropdownToolbar.getItems(); - dropDownToolbarItems.forEach(function (item) { - _this3._popupDropdownToolbar.removeItem(item, false); - - var itemLength = _this3.getItems().length; - _get(DefaultToolbar.prototype.__proto__ || Object.getPrototypeOf(DefaultToolbar.prototype), 'insertItem', _this3).call(_this3, itemLength, item); - }); - - this.removeItem(this._moreButton, false); - _get(DefaultToolbar.prototype.__proto__ || Object.getPrototypeOf(DefaultToolbar.prototype), 'insertItem', this).call(this, 0, this._moreButton); - - var toolbarHeight = this.$el.height(); - var defaultToolbarItems = this.getItems(); - var overflowItems = defaultToolbarItems.filter(function (item) { - return item.$el.position().top > toolbarHeight; - }); - - overflowItems.forEach(function (item) { - _this3.removeItem(item, false); - _this3._popupDropdownToolbar.addItem(item); - }); - - this._arrangeMoreButton(); - } - }, { - key: '_arrangeMoreButton', - value: function _arrangeMoreButton() { - if (!this._popupDropdownToolbar) { - return; - } - - this.removeItem(this._moreButton, false); - - var hasOverflow = this._popupDropdownToolbar.getItems().length > 0; - var itemLength = this.getItems().length; - if (hasOverflow) { - _get(DefaultToolbar.prototype.__proto__ || Object.getPrototypeOf(DefaultToolbar.prototype), 'insertItem', this).call(this, itemLength, this._moreButton); - } - } - - /** - * destroy - * @override - */ - - }, { - key: 'destroy', - value: function destroy() { - if (this._observer) { - this._observer.disconnect(); - this._observer = null; - } - } - }]); - - return DefaultToolbar; -}(_toolbar2.default); - -exports.default = DefaultToolbar; - -/***/ }), -/* 98 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* WEBPACK VAR INJECTION */(function(global) {/** - * A collection of shims that provide minimal functionality of the ES6 collections. - * - * These implementations are not meant to be used outside of the ResizeObserver - * modules as they cover only a limited range of use cases. - */ -/* eslint-disable require-jsdoc, valid-jsdoc */ -var MapShim = (function () { - if (typeof Map !== 'undefined') { - return Map; - } - /** - * Returns index in provided array that matches the specified key. - * - * @param {Array} arr - * @param {*} key - * @returns {number} - */ - function getIndex(arr, key) { - var result = -1; - arr.some(function (entry, index) { - if (entry[0] === key) { - result = index; - return true; - } - return false; - }); - return result; - } - return /** @class */ (function () { - function class_1() { - this.__entries__ = []; - } - Object.defineProperty(class_1.prototype, "size", { - /** - * @returns {boolean} - */ - get: function () { - return this.__entries__.length; - }, - enumerable: true, - configurable: true - }); - /** - * @param {*} key - * @returns {*} - */ - class_1.prototype.get = function (key) { - var index = getIndex(this.__entries__, key); - var entry = this.__entries__[index]; - return entry && entry[1]; - }; - /** - * @param {*} key - * @param {*} value - * @returns {void} - */ - class_1.prototype.set = function (key, value) { - var index = getIndex(this.__entries__, key); - if (~index) { - this.__entries__[index][1] = value; - } - else { - this.__entries__.push([key, value]); - } - }; - /** - * @param {*} key - * @returns {void} - */ - class_1.prototype.delete = function (key) { - var entries = this.__entries__; - var index = getIndex(entries, key); - if (~index) { - entries.splice(index, 1); - } - }; - /** - * @param {*} key - * @returns {void} - */ - class_1.prototype.has = function (key) { - return !!~getIndex(this.__entries__, key); - }; - /** - * @returns {void} - */ - class_1.prototype.clear = function () { - this.__entries__.splice(0); - }; - /** - * @param {Function} callback - * @param {*} [ctx=null] - * @returns {void} - */ - class_1.prototype.forEach = function (callback, ctx) { - if (ctx === void 0) { ctx = null; } - for (var _i = 0, _a = this.__entries__; _i < _a.length; _i++) { - var entry = _a[_i]; - callback.call(ctx, entry[1], entry[0]); - } - }; - return class_1; - }()); -})(); - -/** - * Detects whether window and document objects are available in current environment. - */ -var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && window.document === document; - -// Returns global object of a current environment. -var global$1 = (function () { - if (typeof global !== 'undefined' && global.Math === Math) { - return global; - } - if (typeof self !== 'undefined' && self.Math === Math) { - return self; - } - if (typeof window !== 'undefined' && window.Math === Math) { - return window; - } - // eslint-disable-next-line no-new-func - return Function('return this')(); -})(); - -/** - * A shim for the requestAnimationFrame which falls back to the setTimeout if - * first one is not supported. - * - * @returns {number} Requests' identifier. - */ -var requestAnimationFrame$1 = (function () { - if (typeof requestAnimationFrame === 'function') { - // It's required to use a bounded function because IE sometimes throws - // an "Invalid calling object" error if rAF is invoked without the global - // object on the left hand side. - return requestAnimationFrame.bind(global$1); - } - return function (callback) { return setTimeout(function () { return callback(Date.now()); }, 1000 / 60); }; -})(); - -// Defines minimum timeout before adding a trailing call. -var trailingTimeout = 2; -/** - * Creates a wrapper function which ensures that provided callback will be - * invoked only once during the specified delay period. - * - * @param {Function} callback - Function to be invoked after the delay period. - * @param {number} delay - Delay after which to invoke callback. - * @returns {Function} - */ -function throttle (callback, delay) { - var leadingCall = false, trailingCall = false, lastCallTime = 0; - /** - * Invokes the original callback function and schedules new invocation if - * the "proxy" was called during current request. - * - * @returns {void} - */ - function resolvePending() { - if (leadingCall) { - leadingCall = false; - callback(); - } - if (trailingCall) { - proxy(); - } - } - /** - * Callback invoked after the specified delay. It will further postpone - * invocation of the original function delegating it to the - * requestAnimationFrame. - * - * @returns {void} - */ - function timeoutCallback() { - requestAnimationFrame$1(resolvePending); - } - /** - * Schedules invocation of the original function. - * - * @returns {void} - */ - function proxy() { - var timeStamp = Date.now(); - if (leadingCall) { - // Reject immediately following calls. - if (timeStamp - lastCallTime < trailingTimeout) { - return; - } - // Schedule new call to be in invoked when the pending one is resolved. - // This is important for "transitions" which never actually start - // immediately so there is a chance that we might miss one if change - // happens amids the pending invocation. - trailingCall = true; - } - else { - leadingCall = true; - trailingCall = false; - setTimeout(timeoutCallback, delay); - } - lastCallTime = timeStamp; - } - return proxy; -} - -// Minimum delay before invoking the update of observers. -var REFRESH_DELAY = 20; -// A list of substrings of CSS properties used to find transition events that -// might affect dimensions of observed elements. -var transitionKeys = ['top', 'right', 'bottom', 'left', 'width', 'height', 'size', 'weight']; -// Check if MutationObserver is available. -var mutationObserverSupported = typeof MutationObserver !== 'undefined'; -/** - * Singleton controller class which handles updates of ResizeObserver instances. - */ -var ResizeObserverController = /** @class */ (function () { - /** - * Creates a new instance of ResizeObserverController. - * - * @private - */ - function ResizeObserverController() { - /** - * Indicates whether DOM listeners have been added. - * - * @private {boolean} - */ - this.connected_ = false; - /** - * Tells that controller has subscribed for Mutation Events. - * - * @private {boolean} - */ - this.mutationEventsAdded_ = false; - /** - * Keeps reference to the instance of MutationObserver. - * - * @private {MutationObserver} - */ - this.mutationsObserver_ = null; - /** - * A list of connected observers. - * - * @private {Array} - */ - this.observers_ = []; - this.onTransitionEnd_ = this.onTransitionEnd_.bind(this); - this.refresh = throttle(this.refresh.bind(this), REFRESH_DELAY); - } - /** - * Adds observer to observers list. - * - * @param {ResizeObserverSPI} observer - Observer to be added. - * @returns {void} - */ - ResizeObserverController.prototype.addObserver = function (observer) { - if (!~this.observers_.indexOf(observer)) { - this.observers_.push(observer); - } - // Add listeners if they haven't been added yet. - if (!this.connected_) { - this.connect_(); - } - }; - /** - * Removes observer from observers list. - * - * @param {ResizeObserverSPI} observer - Observer to be removed. - * @returns {void} - */ - ResizeObserverController.prototype.removeObserver = function (observer) { - var observers = this.observers_; - var index = observers.indexOf(observer); - // Remove observer if it's present in registry. - if (~index) { - observers.splice(index, 1); - } - // Remove listeners if controller has no connected observers. - if (!observers.length && this.connected_) { - this.disconnect_(); - } - }; - /** - * Invokes the update of observers. It will continue running updates insofar - * it detects changes. - * - * @returns {void} - */ - ResizeObserverController.prototype.refresh = function () { - var changesDetected = this.updateObservers_(); - // Continue running updates if changes have been detected as there might - // be future ones caused by CSS transitions. - if (changesDetected) { - this.refresh(); - } - }; - /** - * Updates every observer from observers list and notifies them of queued - * entries. - * - * @private - * @returns {boolean} Returns "true" if any observer has detected changes in - * dimensions of it's elements. - */ - ResizeObserverController.prototype.updateObservers_ = function () { - // Collect observers that have active observations. - var activeObservers = this.observers_.filter(function (observer) { - return observer.gatherActive(), observer.hasActive(); - }); - // Deliver notifications in a separate cycle in order to avoid any - // collisions between observers, e.g. when multiple instances of - // ResizeObserver are tracking the same element and the callback of one - // of them changes content dimensions of the observed target. Sometimes - // this may result in notifications being blocked for the rest of observers. - activeObservers.forEach(function (observer) { return observer.broadcastActive(); }); - return activeObservers.length > 0; - }; - /** - * Initializes DOM listeners. - * - * @private - * @returns {void} - */ - ResizeObserverController.prototype.connect_ = function () { - // Do nothing if running in a non-browser environment or if listeners - // have been already added. - if (!isBrowser || this.connected_) { - return; - } - // Subscription to the "Transitionend" event is used as a workaround for - // delayed transitions. This way it's possible to capture at least the - // final state of an element. - document.addEventListener('transitionend', this.onTransitionEnd_); - window.addEventListener('resize', this.refresh); - if (mutationObserverSupported) { - this.mutationsObserver_ = new MutationObserver(this.refresh); - this.mutationsObserver_.observe(document, { - attributes: true, - childList: true, - characterData: true, - subtree: true - }); - } - else { - document.addEventListener('DOMSubtreeModified', this.refresh); - this.mutationEventsAdded_ = true; - } - this.connected_ = true; - }; - /** - * Removes DOM listeners. - * - * @private - * @returns {void} - */ - ResizeObserverController.prototype.disconnect_ = function () { - // Do nothing if running in a non-browser environment or if listeners - // have been already removed. - if (!isBrowser || !this.connected_) { - return; - } - document.removeEventListener('transitionend', this.onTransitionEnd_); - window.removeEventListener('resize', this.refresh); - if (this.mutationsObserver_) { - this.mutationsObserver_.disconnect(); - } - if (this.mutationEventsAdded_) { - document.removeEventListener('DOMSubtreeModified', this.refresh); - } - this.mutationsObserver_ = null; - this.mutationEventsAdded_ = false; - this.connected_ = false; - }; - /** - * "Transitionend" event handler. - * - * @private - * @param {TransitionEvent} event - * @returns {void} - */ - ResizeObserverController.prototype.onTransitionEnd_ = function (_a) { - var _b = _a.propertyName, propertyName = _b === void 0 ? '' : _b; - // Detect whether transition may affect dimensions of an element. - var isReflowProperty = transitionKeys.some(function (key) { - return !!~propertyName.indexOf(key); - }); - if (isReflowProperty) { - this.refresh(); - } - }; - /** - * Returns instance of the ResizeObserverController. - * - * @returns {ResizeObserverController} - */ - ResizeObserverController.getInstance = function () { - if (!this.instance_) { - this.instance_ = new ResizeObserverController(); - } - return this.instance_; - }; - /** - * Holds reference to the controller's instance. - * - * @private {ResizeObserverController} - */ - ResizeObserverController.instance_ = null; - return ResizeObserverController; -}()); - -/** - * Defines non-writable/enumerable properties of the provided target object. - * - * @param {Object} target - Object for which to define properties. - * @param {Object} props - Properties to be defined. - * @returns {Object} Target object. - */ -var defineConfigurable = (function (target, props) { - for (var _i = 0, _a = Object.keys(props); _i < _a.length; _i++) { - var key = _a[_i]; - Object.defineProperty(target, key, { - value: props[key], - enumerable: false, - writable: false, - configurable: true - }); - } - return target; -}); - -/** - * Returns the global object associated with provided element. - * - * @param {Object} target - * @returns {Object} - */ -var getWindowOf = (function (target) { - // Assume that the element is an instance of Node, which means that it - // has the "ownerDocument" property from which we can retrieve a - // corresponding global object. - var ownerGlobal = target && target.ownerDocument && target.ownerDocument.defaultView; - // Return the local global object if it's not possible extract one from - // provided element. - return ownerGlobal || global$1; -}); - -// Placeholder of an empty content rectangle. -var emptyRect = createRectInit(0, 0, 0, 0); -/** - * Converts provided string to a number. - * - * @param {number|string} value - * @returns {number} - */ -function toFloat(value) { - return parseFloat(value) || 0; -} -/** - * Extracts borders size from provided styles. - * - * @param {CSSStyleDeclaration} styles - * @param {...string} positions - Borders positions (top, right, ...) - * @returns {number} - */ -function getBordersSize(styles) { - var positions = []; - for (var _i = 1; _i < arguments.length; _i++) { - positions[_i - 1] = arguments[_i]; - } - return positions.reduce(function (size, position) { - var value = styles['border-' + position + '-width']; - return size + toFloat(value); - }, 0); -} -/** - * Extracts paddings sizes from provided styles. - * - * @param {CSSStyleDeclaration} styles - * @returns {Object} Paddings box. - */ -function getPaddings(styles) { - var positions = ['top', 'right', 'bottom', 'left']; - var paddings = {}; - for (var _i = 0, positions_1 = positions; _i < positions_1.length; _i++) { - var position = positions_1[_i]; - var value = styles['padding-' + position]; - paddings[position] = toFloat(value); - } - return paddings; -} -/** - * Calculates content rectangle of provided SVG element. - * - * @param {SVGGraphicsElement} target - Element content rectangle of which needs - * to be calculated. - * @returns {DOMRectInit} - */ -function getSVGContentRect(target) { - var bbox = target.getBBox(); - return createRectInit(0, 0, bbox.width, bbox.height); -} -/** - * Calculates content rectangle of provided HTMLElement. - * - * @param {HTMLElement} target - Element for which to calculate the content rectangle. - * @returns {DOMRectInit} - */ -function getHTMLElementContentRect(target) { - // Client width & height properties can't be - // used exclusively as they provide rounded values. - var clientWidth = target.clientWidth, clientHeight = target.clientHeight; - // By this condition we can catch all non-replaced inline, hidden and - // detached elements. Though elements with width & height properties less - // than 0.5 will be discarded as well. - // - // Without it we would need to implement separate methods for each of - // those cases and it's not possible to perform a precise and performance - // effective test for hidden elements. E.g. even jQuery's ':visible' filter - // gives wrong results for elements with width & height less than 0.5. - if (!clientWidth && !clientHeight) { - return emptyRect; - } - var styles = getWindowOf(target).getComputedStyle(target); - var paddings = getPaddings(styles); - var horizPad = paddings.left + paddings.right; - var vertPad = paddings.top + paddings.bottom; - // Computed styles of width & height are being used because they are the - // only dimensions available to JS that contain non-rounded values. It could - // be possible to utilize the getBoundingClientRect if only it's data wasn't - // affected by CSS transformations let alone paddings, borders and scroll bars. - var width = toFloat(styles.width), height = toFloat(styles.height); - // Width & height include paddings and borders when the 'border-box' box - // model is applied (except for IE). - if (styles.boxSizing === 'border-box') { - // Following conditions are required to handle Internet Explorer which - // doesn't include paddings and borders to computed CSS dimensions. - // - // We can say that if CSS dimensions + paddings are equal to the "client" - // properties then it's either IE, and thus we don't need to subtract - // anything, or an element merely doesn't have paddings/borders styles. - if (Math.round(width + horizPad) !== clientWidth) { - width -= getBordersSize(styles, 'left', 'right') + horizPad; - } - if (Math.round(height + vertPad) !== clientHeight) { - height -= getBordersSize(styles, 'top', 'bottom') + vertPad; - } - } - // Following steps can't be applied to the document's root element as its - // client[Width/Height] properties represent viewport area of the window. - // Besides, it's as well not necessary as the itself neither has - // rendered scroll bars nor it can be clipped. - if (!isDocumentElement(target)) { - // In some browsers (only in Firefox, actually) CSS width & height - // include scroll bars size which can be removed at this step as scroll - // bars are the only difference between rounded dimensions + paddings - // and "client" properties, though that is not always true in Chrome. - var vertScrollbar = Math.round(width + horizPad) - clientWidth; - var horizScrollbar = Math.round(height + vertPad) - clientHeight; - // Chrome has a rather weird rounding of "client" properties. - // E.g. for an element with content width of 314.2px it sometimes gives - // the client width of 315px and for the width of 314.7px it may give - // 314px. And it doesn't happen all the time. So just ignore this delta - // as a non-relevant. - if (Math.abs(vertScrollbar) !== 1) { - width -= vertScrollbar; - } - if (Math.abs(horizScrollbar) !== 1) { - height -= horizScrollbar; - } - } - return createRectInit(paddings.left, paddings.top, width, height); -} -/** - * Checks whether provided element is an instance of the SVGGraphicsElement. - * - * @param {Element} target - Element to be checked. - * @returns {boolean} - */ -var isSVGGraphicsElement = (function () { - // Some browsers, namely IE and Edge, don't have the SVGGraphicsElement - // interface. - if (typeof SVGGraphicsElement !== 'undefined') { - return function (target) { return target instanceof getWindowOf(target).SVGGraphicsElement; }; - } - // If it's so, then check that element is at least an instance of the - // SVGElement and that it has the "getBBox" method. - // eslint-disable-next-line no-extra-parens - return function (target) { return (target instanceof getWindowOf(target).SVGElement && - typeof target.getBBox === 'function'); }; -})(); -/** - * Checks whether provided element is a document element (). - * - * @param {Element} target - Element to be checked. - * @returns {boolean} - */ -function isDocumentElement(target) { - return target === getWindowOf(target).document.documentElement; -} -/** - * Calculates an appropriate content rectangle for provided html or svg element. - * - * @param {Element} target - Element content rectangle of which needs to be calculated. - * @returns {DOMRectInit} - */ -function getContentRect(target) { - if (!isBrowser) { - return emptyRect; - } - if (isSVGGraphicsElement(target)) { - return getSVGContentRect(target); - } - return getHTMLElementContentRect(target); -} -/** - * Creates rectangle with an interface of the DOMRectReadOnly. - * Spec: https://drafts.fxtf.org/geometry/#domrectreadonly - * - * @param {DOMRectInit} rectInit - Object with rectangle's x/y coordinates and dimensions. - * @returns {DOMRectReadOnly} - */ -function createReadOnlyRect(_a) { - var x = _a.x, y = _a.y, width = _a.width, height = _a.height; - // If DOMRectReadOnly is available use it as a prototype for the rectangle. - var Constr = typeof DOMRectReadOnly !== 'undefined' ? DOMRectReadOnly : Object; - var rect = Object.create(Constr.prototype); - // Rectangle's properties are not writable and non-enumerable. - defineConfigurable(rect, { - x: x, y: y, width: width, height: height, - top: y, - right: x + width, - bottom: height + y, - left: x - }); - return rect; -} -/** - * Creates DOMRectInit object based on the provided dimensions and the x/y coordinates. - * Spec: https://drafts.fxtf.org/geometry/#dictdef-domrectinit - * - * @param {number} x - X coordinate. - * @param {number} y - Y coordinate. - * @param {number} width - Rectangle's width. - * @param {number} height - Rectangle's height. - * @returns {DOMRectInit} - */ -function createRectInit(x, y, width, height) { - return { x: x, y: y, width: width, height: height }; -} - -/** - * Class that is responsible for computations of the content rectangle of - * provided DOM element and for keeping track of it's changes. - */ -var ResizeObservation = /** @class */ (function () { - /** - * Creates an instance of ResizeObservation. - * - * @param {Element} target - Element to be observed. - */ - function ResizeObservation(target) { - /** - * Broadcasted width of content rectangle. - * - * @type {number} - */ - this.broadcastWidth = 0; - /** - * Broadcasted height of content rectangle. - * - * @type {number} - */ - this.broadcastHeight = 0; - /** - * Reference to the last observed content rectangle. - * - * @private {DOMRectInit} - */ - this.contentRect_ = createRectInit(0, 0, 0, 0); - this.target = target; - } - /** - * Updates content rectangle and tells whether it's width or height properties - * have changed since the last broadcast. - * - * @returns {boolean} - */ - ResizeObservation.prototype.isActive = function () { - var rect = getContentRect(this.target); - this.contentRect_ = rect; - return (rect.width !== this.broadcastWidth || - rect.height !== this.broadcastHeight); - }; - /** - * Updates 'broadcastWidth' and 'broadcastHeight' properties with a data - * from the corresponding properties of the last observed content rectangle. - * - * @returns {DOMRectInit} Last observed content rectangle. - */ - ResizeObservation.prototype.broadcastRect = function () { - var rect = this.contentRect_; - this.broadcastWidth = rect.width; - this.broadcastHeight = rect.height; - return rect; - }; - return ResizeObservation; -}()); - -var ResizeObserverEntry = /** @class */ (function () { - /** - * Creates an instance of ResizeObserverEntry. - * - * @param {Element} target - Element that is being observed. - * @param {DOMRectInit} rectInit - Data of the element's content rectangle. - */ - function ResizeObserverEntry(target, rectInit) { - var contentRect = createReadOnlyRect(rectInit); - // According to the specification following properties are not writable - // and are also not enumerable in the native implementation. - // - // Property accessors are not being used as they'd require to define a - // private WeakMap storage which may cause memory leaks in browsers that - // don't support this type of collections. - defineConfigurable(this, { target: target, contentRect: contentRect }); - } - return ResizeObserverEntry; -}()); - -var ResizeObserverSPI = /** @class */ (function () { - /** - * Creates a new instance of ResizeObserver. - * - * @param {ResizeObserverCallback} callback - Callback function that is invoked - * when one of the observed elements changes it's content dimensions. - * @param {ResizeObserverController} controller - Controller instance which - * is responsible for the updates of observer. - * @param {ResizeObserver} callbackCtx - Reference to the public - * ResizeObserver instance which will be passed to callback function. - */ - function ResizeObserverSPI(callback, controller, callbackCtx) { - /** - * Collection of resize observations that have detected changes in dimensions - * of elements. - * - * @private {Array} - */ - this.activeObservations_ = []; - /** - * Registry of the ResizeObservation instances. - * - * @private {Map} - */ - this.observations_ = new MapShim(); - if (typeof callback !== 'function') { - throw new TypeError('The callback provided as parameter 1 is not a function.'); - } - this.callback_ = callback; - this.controller_ = controller; - this.callbackCtx_ = callbackCtx; - } - /** - * Starts observing provided element. - * - * @param {Element} target - Element to be observed. - * @returns {void} - */ - ResizeObserverSPI.prototype.observe = function (target) { - if (!arguments.length) { - throw new TypeError('1 argument required, but only 0 present.'); - } - // Do nothing if current environment doesn't have the Element interface. - if (typeof Element === 'undefined' || !(Element instanceof Object)) { - return; - } - if (!(target instanceof getWindowOf(target).Element)) { - throw new TypeError('parameter 1 is not of type "Element".'); - } - var observations = this.observations_; - // Do nothing if element is already being observed. - if (observations.has(target)) { - return; - } - observations.set(target, new ResizeObservation(target)); - this.controller_.addObserver(this); - // Force the update of observations. - this.controller_.refresh(); - }; - /** - * Stops observing provided element. - * - * @param {Element} target - Element to stop observing. - * @returns {void} - */ - ResizeObserverSPI.prototype.unobserve = function (target) { - if (!arguments.length) { - throw new TypeError('1 argument required, but only 0 present.'); - } - // Do nothing if current environment doesn't have the Element interface. - if (typeof Element === 'undefined' || !(Element instanceof Object)) { - return; - } - if (!(target instanceof getWindowOf(target).Element)) { - throw new TypeError('parameter 1 is not of type "Element".'); - } - var observations = this.observations_; - // Do nothing if element is not being observed. - if (!observations.has(target)) { - return; - } - observations.delete(target); - if (!observations.size) { - this.controller_.removeObserver(this); - } - }; - /** - * Stops observing all elements. - * - * @returns {void} - */ - ResizeObserverSPI.prototype.disconnect = function () { - this.clearActive(); - this.observations_.clear(); - this.controller_.removeObserver(this); - }; - /** - * Collects observation instances the associated element of which has changed - * it's content rectangle. - * - * @returns {void} - */ - ResizeObserverSPI.prototype.gatherActive = function () { - var _this = this; - this.clearActive(); - this.observations_.forEach(function (observation) { - if (observation.isActive()) { - _this.activeObservations_.push(observation); - } - }); - }; - /** - * Invokes initial callback function with a list of ResizeObserverEntry - * instances collected from active resize observations. - * - * @returns {void} - */ - ResizeObserverSPI.prototype.broadcastActive = function () { - // Do nothing if observer doesn't have active observations. - if (!this.hasActive()) { - return; - } - var ctx = this.callbackCtx_; - // Create ResizeObserverEntry instance for every active observation. - var entries = this.activeObservations_.map(function (observation) { - return new ResizeObserverEntry(observation.target, observation.broadcastRect()); - }); - this.callback_.call(ctx, entries, ctx); - this.clearActive(); - }; - /** - * Clears the collection of active observations. - * - * @returns {void} - */ - ResizeObserverSPI.prototype.clearActive = function () { - this.activeObservations_.splice(0); - }; - /** - * Tells whether observer has active observations. - * - * @returns {boolean} - */ - ResizeObserverSPI.prototype.hasActive = function () { - return this.activeObservations_.length > 0; - }; - return ResizeObserverSPI; -}()); - -// Registry of internal observers. If WeakMap is not available use current shim -// for the Map collection as it has all required methods and because WeakMap -// can't be fully polyfilled anyway. -var observers = typeof WeakMap !== 'undefined' ? new WeakMap() : new MapShim(); -/** - * ResizeObserver API. Encapsulates the ResizeObserver SPI implementation - * exposing only those methods and properties that are defined in the spec. - */ -var ResizeObserver = /** @class */ (function () { - /** - * Creates a new instance of ResizeObserver. - * - * @param {ResizeObserverCallback} callback - Callback that is invoked when - * dimensions of the observed elements change. - */ - function ResizeObserver(callback) { - if (!(this instanceof ResizeObserver)) { - throw new TypeError('Cannot call a class as a function.'); - } - if (!arguments.length) { - throw new TypeError('1 argument required, but only 0 present.'); - } - var controller = ResizeObserverController.getInstance(); - var observer = new ResizeObserverSPI(callback, controller, this); - observers.set(this, observer); - } - return ResizeObserver; -}()); -// Expose public methods of ResizeObserver. -[ - 'observe', - 'unobserve', - 'disconnect' -].forEach(function (method) { - ResizeObserver.prototype[method] = function () { - var _a; - return (_a = observers.get(this))[method].apply(_a, arguments); - }; -}); - -var index = (function () { - // Export existing implementation if available. - if (typeof global$1.ResizeObserver !== 'undefined') { - return global$1.ResizeObserver; - } - return ResizeObserver; -})(); - -/* harmony default export */ __webpack_exports__["default"] = (index); - -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(11))) - -/***/ }), -/* 99 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _button = __webpack_require__(21); - -var _button2 = _interopRequireDefault(_button); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements UI Button - * @author NHN FE Development Lab - */ - - -/** - * Toolbar Button UI - * @ignore - */ -var ToolbarButton = function (_Button) { - _inherits(ToolbarButton, _Button); - - function ToolbarButton() { - _classCallCheck(this, ToolbarButton); - - return _possibleConstructorReturn(this, (ToolbarButton.__proto__ || Object.getPrototypeOf(ToolbarButton)).apply(this, arguments)); - } - - return ToolbarButton; -}(_button2.default); - -exports.default = ToolbarButton; - -/***/ }), -/* 100 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _layerpopup = __webpack_require__(7); - -var _layerpopup2 = _interopRequireDefault(_layerpopup); - -var _toolbar = __webpack_require__(43); - -var _toolbar2 = _interopRequireDefault(_toolbar); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview implements DefaultToolbar - * @author NHN FE Development Lab - */ - - -/** - * Class PopupDropdownToolbar - * @param {LayerPopupOption} options - layer popup option - * @ignore - */ -var PopupDropdownToolbar = function (_LayerPopup) { - _inherits(PopupDropdownToolbar, _LayerPopup); - - function PopupDropdownToolbar(options) { - _classCallCheck(this, PopupDropdownToolbar); - - options = _tuiCodeSnippet2.default.extend({ - header: false, - className: 'te-dropdown-toolbar' - }, options); - return _possibleConstructorReturn(this, (PopupDropdownToolbar.__proto__ || Object.getPrototypeOf(PopupDropdownToolbar)).call(this, options)); - } - - /** - * get toolbar instance it contains - * @returns {Toolbar} - toolbar instance - */ - - /** - * open event string - * @type {string} - */ - - - _createClass(PopupDropdownToolbar, [{ - key: 'getToolbar', - value: function getToolbar() { - return this._toolbar; - } - - /** - * get toolbar items - * @returns {ToolbarItem[]} - toolbar items - */ - - }, { - key: 'getItems', - value: function getItems() { - return this.getToolbar().getItems(); - } - - /** - * get toolbar item at given index - * @param {number} index - item index - * @returns {ToolbarItem} - toolbar item at the index - */ - - }, { - key: 'getItem', - value: function getItem(index) { - return this.getToolbar().getItem(index); - } - - /** - * set toolbar items - * @param {ToolbarItem[]} items - toolbar items - */ - - }, { - key: 'setItems', - value: function setItems(items) { - this.getToolbar().setItems(items); - } - - /** - * add toolbar item - * @param {ToolbarItem|string|object} item - toolbar item - */ - - }, { - key: 'addItem', - value: function addItem(item) { - this.getToolbar().addItem(item); - } - - /** - * insert toolbar item - * @param {number} index - index at given item inserted - * @param {ToolbarItem|string|object} item - toolbar item - */ - - }, { - key: 'insertItem', - value: function insertItem(index, item) { - this.getToolbar().insertItem(index, item); - } - - /** - * get index of given item - * @param {ToolbarItem} item - toolbar item - * @returns {number} - index of given toolbar item - */ - - }, { - key: 'indexOfItem', - value: function indexOfItem(item) { - return this.getToolbar().indexOfItem(item); - } - - /** - * remove an item - * @param {number} index - item index to remove - * @param {boolean} destroy - destroy item or not - * @returns {ToolbarItem} - removed item - */ - - }, { - key: 'removeItem', - value: function removeItem(index, destroy) { - return this.getToolbar().removeItem(index, destroy); - } - - /** - * remove all toolbar items - */ - - }, { - key: 'removeAllItems', - value: function removeAllItems() { - this.getToolbar().removeAllItems(); - } - - /** - * init instance. - * store properties & prepare before initialize DOM - * @param {LayerPopupOption} options - layer popup options - * @private - * @override - */ - - }, { - key: '_initInstance', - value: function _initInstance(options) { - _get(PopupDropdownToolbar.prototype.__proto__ || Object.getPrototypeOf(PopupDropdownToolbar.prototype), '_initInstance', this).call(this, options); - - var $button = options.$button, - eventManager = options.eventManager; - - - this._$button = $button; - this._eventManager = eventManager; - this._toolbar = new _toolbar2.default(eventManager); - } - - /** - * initialize DOM, render popup - * @private - * @override - */ - - }, { - key: '_initDOM', - value: function _initDOM() { - _get(PopupDropdownToolbar.prototype.__proto__ || Object.getPrototypeOf(PopupDropdownToolbar.prototype), '_initDOM', this).call(this); - - this.setContent(this._toolbar.$el); - } - - /** - * bind editor events - * @private - * @override - */ - - }, { - key: '_initEditorEvent', - value: function _initEditorEvent() { - var _this2 = this; - - _get(PopupDropdownToolbar.prototype.__proto__ || Object.getPrototypeOf(PopupDropdownToolbar.prototype), '_initEditorEvent', this).call(this); - - this._eventManager.listen('focus', function () { - return _this2.hide(); - }); - this._eventManager.listen('closeAllPopup', function () { - return _this2.hide(); - }); - this._eventManager.listen(PopupDropdownToolbar.OPEN_EVENT, function () { - var isShown = _this2.isShow(); - _this2._eventManager.emit('closeAllPopup'); - if (!isShown) { - _this2.show(); - } - - // to give toolbar element enough width before the calculation - _this2.$el.css({ - left: '-1000px' - }); - var $button = _this2._$button; - var position = $button.position(); - var buttonOuterHeightWithMargin = $button.outerHeight(true); - var buttonMarginBottom = (buttonOuterHeightWithMargin - $button.outerHeight()) / 2; - var top = position.top + buttonOuterHeightWithMargin - buttonMarginBottom; - var left = position.left + $button.outerWidth(true) - _this2.$el.outerWidth(true); - - _this2.$el.css({ - top: top, - left: left - }); - }); - } - }]); - - return PopupDropdownToolbar; -}(_layerpopup2.default); - -Object.defineProperty(PopupDropdownToolbar, 'OPEN_EVENT', { - enumerable: true, - writable: true, - value: 'openDropdownToolbar' -}); -exports.default = PopupDropdownToolbar; - -/***/ }), -/* 101 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _uicontroller = __webpack_require__(14); - -var _uicontroller2 = _interopRequireDefault(_uicontroller); - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements ui mode switch - * @author NHN FE Development Lab - */ - - -var MARKDOWN = 'markdown'; -var WYSIWYG = 'wysiwyg'; - -/** - * Class ModeSwitch - * UI Control for switch between Markdown and WYSIWYG - * @param {jQuery} $rootElement - root jquery element - * @param {string} initialType - initial type of editor - */ - -var ModeSwitch = function (_UIController) { - _inherits(ModeSwitch, _UIController); - - /** - * current mode - * @type {String} - * @private - */ - - /** - * mode switch type - * @property {string} MARKDOWN - Markdown - * @property {string} WYSIWYG - WYSIWYG - * @static - * @ignore - */ - function ModeSwitch($rootElement, initialType) { - _classCallCheck(this, ModeSwitch); - - var _this = _possibleConstructorReturn(this, (ModeSwitch.__proto__ || Object.getPrototypeOf(ModeSwitch)).call(this, { - tagName: 'div', - className: 'te-mode-switch' - })); - - Object.defineProperty(_this, '_buttons', { - enumerable: true, - writable: true, - value: {} - }); - - - _this._render($rootElement); - _this._switchType(_tuiCodeSnippet2.default.isExisty(initialType) ? initialType : MARKDOWN); - return _this; - } - - /** - * is the switch tab bar shown - * @returns {Boolean} - showing status - */ - - - /** - * root element - * @type {jQuery} - * @private - */ - - - /** - * mode switch buttons - * @type {Object} - * @private - */ - - - _createClass(ModeSwitch, [{ - key: 'isShown', - value: function isShown() { - return this._$rootElement.css('display') === 'block'; - } - - /** - * show switch tab bar - */ - - }, { - key: 'show', - value: function show() { - this._$rootElement.css('display', 'block'); - } - - /** - * hide switch tab bar - */ - - }, { - key: 'hide', - value: function hide() { - this._$rootElement.css('display', 'none'); - } - }, { - key: '_render', - value: function _render($rootElement) { - this._buttons.$markdown = (0, _jquery2.default)(''); - this._buttons.$wysiwyg = (0, _jquery2.default)(''); - this.$el.append(this._buttons.$markdown); - this.$el.append(this._buttons.$wysiwyg); - - if ($rootElement) { - $rootElement.append(this.$el); - this._$rootElement = $rootElement; - } - - this.on('click .markdown', this._changeMarkdown.bind(this)); - this.on('click .wysiwyg', this._changeWysiwyg.bind(this)); - - this.show(); - } - }, { - key: '_changeMarkdown', - value: function _changeMarkdown() { - this._switchType(MARKDOWN); - } - }, { - key: '_changeWysiwyg', - value: function _changeWysiwyg() { - this._switchType(WYSIWYG); - } - }, { - key: '_setActiveButton', - value: function _setActiveButton(type) { - this._buttons.$markdown.removeClass('active'); - this._buttons.$wysiwyg.removeClass('active'); - this._buttons['$' + type].addClass('active'); - } - }, { - key: '_switchType', - value: function _switchType(type) { - if (this._type === type) { - return; - } - - this._type = type; - this._setActiveButton(type); - this.trigger('modeSwitched', this._type); - } - }]); - - return ModeSwitch; -}(_uicontroller2.default); - -Object.defineProperty(ModeSwitch, 'TYPE', { - enumerable: true, - writable: true, - value: { - MARKDOWN: MARKDOWN, - WYSIWYG: WYSIWYG - } -}); -exports.default = ModeSwitch; - -/***/ }), -/* 102 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _layerpopup = __webpack_require__(7); - -var _layerpopup2 = _interopRequireDefault(_layerpopup); - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements PopupAddLink - * @author NHN FE Development Lab - */ - - -var URL_REGEX = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})(\/([^\s]*))?$/; - -/** - * Class PopupAddLink - * It implements a link Add Popup - * @param {LayerPopupOption} options - layer popup options - * @ignore - */ - -var PopupAddLink = function (_LayerPopup) { - _inherits(PopupAddLink, _LayerPopup); - - function PopupAddLink(options) { - _classCallCheck(this, PopupAddLink); - - var POPUP_CONTENT = '\n \n \n \n \n
    \n \n \n
    \n '; - options = _tuiCodeSnippet2.default.extend({ - header: true, - title: _i18n2.default.get('Insert link'), - className: 'te-popup-add-link tui-editor-popup', - content: POPUP_CONTENT - }, options); - return _possibleConstructorReturn(this, (PopupAddLink.__proto__ || Object.getPrototypeOf(PopupAddLink)).call(this, options)); - } - - /** - * init instance. - * store properties & prepare before initialize DOM - * @param {LayerPopupOption} options - layer popup options - * @private - * @override - */ - - - _createClass(PopupAddLink, [{ - key: '_initInstance', - value: function _initInstance(options) { - _get(PopupAddLink.prototype.__proto__ || Object.getPrototypeOf(PopupAddLink.prototype), '_initInstance', this).call(this, options); - - this._editor = options.editor; - this._eventManager = options.editor.eventManager; - } - - /** - * initialize DOM, render popup - * @private - * @override - */ - - }, { - key: '_initDOM', - value: function _initDOM() { - _get(PopupAddLink.prototype.__proto__ || Object.getPrototypeOf(PopupAddLink.prototype), '_initDOM', this).call(this); - - var el = this.$el.get(0); - this._inputText = el.querySelector('.te-link-text-input'); - this._inputURL = el.querySelector('.te-url-input'); - } - - /** - * bind DOM events - * @private - * @override - */ - - }, { - key: '_initDOMEvent', - value: function _initDOMEvent() { - var _this2 = this; - - _get(PopupAddLink.prototype.__proto__ || Object.getPrototypeOf(PopupAddLink.prototype), '_initDOMEvent', this).call(this); - - this.on('click .te-close-button', function () { - return _this2.hide(); - }); - this.on('click .te-ok-button', function () { - return _this2._addLink(); - }); - - this.on('shown', function () { - var inputText = _this2._inputText; - var inputURL = _this2._inputURL; - - var selectedText = _this2._editor.getSelectedText().trim(); - - inputText.value = selectedText; - if (URL_REGEX.exec(selectedText)) { - inputURL.value = selectedText; - } - - inputURL.focus(); - }); - - this.on('hidden', function () { - _this2._resetInputs(); - }); - } - - /** - * bind editor events - * @private - * @override - */ - - }, { - key: '_initEditorEvent', - value: function _initEditorEvent() { - var _this3 = this; - - _get(PopupAddLink.prototype.__proto__ || Object.getPrototypeOf(PopupAddLink.prototype), '_initEditorEvent', this).call(this); - - var eventManager = this._eventManager; - eventManager.listen('focus', function () { - return _this3.hide(); - }); - eventManager.listen('closeAllPopup', function () { - return _this3.hide(); - }); - eventManager.listen('openPopupAddLink', function () { - eventManager.emit('closeAllPopup'); - _this3.show(); - }); - } - }, { - key: '_addLink', - value: function _addLink() { - var _getValue2 = this._getValue(), - url = _getValue2.url, - linkText = _getValue2.linkText; - - this._clearValidationStyle(); - - if (linkText.length < 1) { - (0, _jquery2.default)(this._inputText).addClass('wrong'); - - return; - } - if (url.length < 1) { - (0, _jquery2.default)(this._inputURL).addClass('wrong'); - - return; - } - - this._eventManager.emit('command', 'AddLink', { - linkText: linkText, - url: url - }); - this.hide(); - } - }, { - key: '_getValue', - value: function _getValue() { - var url = this._inputURL.value; - var linkText = this._inputText.value; - - return { - url: url, - linkText: linkText - }; - } - }, { - key: '_clearValidationStyle', - value: function _clearValidationStyle() { - (0, _jquery2.default)(this._inputURL).removeClass('wrong'); - (0, _jquery2.default)(this._inputText).removeClass('wrong'); - } - }, { - key: '_resetInputs', - value: function _resetInputs() { - this._inputText.value = ''; - this._inputURL.value = ''; - this._clearValidationStyle(); - } - }]); - - return PopupAddLink; -}(_layerpopup2.default); - -exports.default = PopupAddLink; - -/***/ }), -/* 103 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _layerpopup = __webpack_require__(7); - -var _layerpopup2 = _interopRequireDefault(_layerpopup); - -var _tab = __webpack_require__(46); - -var _tab2 = _interopRequireDefault(_tab); - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements PopupAddImage - * @author NHN FE Development Lab - */ - - -var CLASS_IMAGE_URL_INPUT = 'te-image-url-input'; -var CLASS_IMAGE_FILE_INPUT = 'te-image-file-input'; -var CLASS_ALT_TEXT_INPUT = 'te-alt-text-input'; -var CLASS_OK_BUTTON = 'te-ok-button'; -var CLASS_CLOSE_BUTTON = 'te-close-button'; -var CLASS_FILE_TYPE = 'te-file-type'; -var CLASS_URL_TYPE = 'te-url-type'; -var CLASS_TAB_SECTION = 'te-tab-section'; -var TYPE_UI = 'ui'; - -/** - * Class PopupAddImage - * It implements a Image Add Popup - * @param {LayerPopupOption} options - layer popup option - * @ignore - */ - -var PopupAddImage = function (_LayerPopup) { - _inherits(PopupAddImage, _LayerPopup); - - function PopupAddImage(options) { - _classCallCheck(this, PopupAddImage); - - var POPUP_CONTENT = '\n
    \n
    \n \n \n
    \n
    \n \n \n
    \n \n \n
    \n \n \n
    \n '; - options = _tuiCodeSnippet2.default.extend({ - header: true, - title: _i18n2.default.get('Insert image'), - className: 'te-popup-add-image tui-editor-popup', - content: POPUP_CONTENT - }, options); - return _possibleConstructorReturn(this, (PopupAddImage.__proto__ || Object.getPrototypeOf(PopupAddImage)).call(this, options)); - } - - /** - * init instance. - * store properties & prepare before initialize DOM - * @param {LayerPopupOption} options - layer popup options - * @private - * @override - */ - - - _createClass(PopupAddImage, [{ - key: '_initInstance', - value: function _initInstance(options) { - _get(PopupAddImage.prototype.__proto__ || Object.getPrototypeOf(PopupAddImage.prototype), '_initInstance', this).call(this, options); - - this.eventManager = options.eventManager; - } - - /** - * initialize DOM, render popup - * @private - * @override - */ - - }, { - key: '_initDOM', - value: function _initDOM() { - _get(PopupAddImage.prototype.__proto__ || Object.getPrototypeOf(PopupAddImage.prototype), '_initDOM', this).call(this); - - var $popup = this.$el; - - this._$imageUrlInput = $popup.find('.' + CLASS_IMAGE_URL_INPUT); - this._$imageFileInput = $popup.find('.' + CLASS_IMAGE_FILE_INPUT); - this._$altTextInput = $popup.find('.' + CLASS_ALT_TEXT_INPUT); - - var $fileTypeSection = $popup.find('.' + CLASS_FILE_TYPE); - var $urlTypeSection = $popup.find('.' + CLASS_URL_TYPE); - var $tabSection = this.$body.find('.' + CLASS_TAB_SECTION); - this.tab = new _tab2.default({ - initName: _i18n2.default.get('File'), - items: [_i18n2.default.get('File'), _i18n2.default.get('URL')], - sections: [$fileTypeSection, $urlTypeSection] - }); - $tabSection.append(this.tab.$el); - } - - /** - * bind DOM events - * @private - * @override - */ - - }, { - key: '_initDOMEvent', - value: function _initDOMEvent() { - var _this2 = this; - - _get(PopupAddImage.prototype.__proto__ || Object.getPrototypeOf(PopupAddImage.prototype), '_initDOMEvent', this).call(this); - - this.on('shown', function () { - return _this2._$imageUrlInput.focus(); - }); - this.on('hidden', function () { - return _this2._resetInputs(); - }); - - this.on('change .' + CLASS_IMAGE_FILE_INPUT, function () { - var filename = _this2._$imageFileInput.val().split('\\').pop(); - _this2._$altTextInput.val(filename); - }); - - this.on('click .' + CLASS_CLOSE_BUTTON, function () { - return _this2.hide(); - }); - this.on('click .' + CLASS_OK_BUTTON, function () { - var imageUrl = _this2._$imageUrlInput.val(); - var altText = _this2._$altTextInput.val(); - - if (imageUrl) { - _this2._applyImage(imageUrl, altText); - } else { - var _$imageFileInput$get = _this2._$imageFileInput.get(0), - files = _$imageFileInput$get.files; - - if (files.length) { - var imageFile = files.item(0); - var hookCallback = function hookCallback(url, text) { - return _this2._applyImage(url, text || altText); - }; - - _this2.eventManager.emit('addImageBlobHook', imageFile, hookCallback, TYPE_UI); - } - } - - _this2.hide(); - }); - - this.tab.on('itemClick', function () { - return _this2._resetInputs(); - }); - } - - /** - * bind editor events - * @private - * @override - */ - - }, { - key: '_initEditorEvent', - value: function _initEditorEvent() { - var _this3 = this; - - _get(PopupAddImage.prototype.__proto__ || Object.getPrototypeOf(PopupAddImage.prototype), '_initEditorEvent', this).call(this); - - this.eventManager.listen('focus', function () { - return _this3.hide(); - }); - this.eventManager.listen('closeAllPopup', function () { - return _this3.hide(); - }); - - this.eventManager.listen('openPopupAddImage', function () { - _this3.eventManager.emit('closeAllPopup'); - _this3.show(); - }); - } - }, { - key: '_applyImage', - value: function _applyImage(imageUrl, altText) { - this.eventManager.emit('command', 'AddImage', { - imageUrl: imageUrl, - altText: altText || 'image' - }); - this.hide(); - } - }, { - key: '_resetInputs', - value: function _resetInputs() { - this.$el.find('input').val(''); - } - - /** - * Remove popup - * @override - */ - - }, { - key: 'remove', - value: function remove() { - this.tab.remove(); - _get(PopupAddImage.prototype.__proto__ || Object.getPrototypeOf(PopupAddImage.prototype), 'remove', this).call(this); - } - }]); - - return PopupAddImage; -}(_layerpopup2.default); - -exports.default = PopupAddImage; - -/***/ }), -/* 104 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.DISABLED_MENU_CLASS_NAME = exports.REMOVE_ROW_MENU_CLASS_NAME = undefined; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _layerpopup = __webpack_require__(7); - -var _layerpopup2 = _interopRequireDefault(_layerpopup); - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements PopupTableUtils - * @author NHN FE Development Lab - */ - - -var REMOVE_ROW_MENU_CLASS_NAME = exports.REMOVE_ROW_MENU_CLASS_NAME = 'te-table-remove-row'; -var DISABLED_MENU_CLASS_NAME = exports.DISABLED_MENU_CLASS_NAME = 'te-context-menu-disabled'; - -/** - * PopupTableUtils - * It implements table utils popup - * @param {LayerPopupOption} options - layer popup options - */ - -var PopupTableUtils = function (_LayerPopup) { - _inherits(PopupTableUtils, _LayerPopup); - - function PopupTableUtils(options) { - _classCallCheck(this, PopupTableUtils); - - var POPUP_CONTENT = '\n \n \n \n \n
    \n \n \n \n
    \n \n '; - options = _tuiCodeSnippet2.default.extend({ - header: false, - className: 'te-popup-table-utils', - content: POPUP_CONTENT - }, options); - return _possibleConstructorReturn(this, (PopupTableUtils.__proto__ || Object.getPrototypeOf(PopupTableUtils)).call(this, options)); - } - - /** - * init instance. - * store properties & prepare before initialize DOM - * @param {LayerPopupOption} options - layer popup options - * @private - * @override - */ - - - _createClass(PopupTableUtils, [{ - key: '_initInstance', - value: function _initInstance(options) { - _get(PopupTableUtils.prototype.__proto__ || Object.getPrototypeOf(PopupTableUtils.prototype), '_initInstance', this).call(this, options); - this.eventManager = options.eventManager; - } - - /** - * bind DOM events - * @private - * @override - */ - - }, { - key: '_initDOMEvent', - value: function _initDOMEvent() { - var _this2 = this; - - _get(PopupTableUtils.prototype.__proto__ || Object.getPrototypeOf(PopupTableUtils.prototype), '_initDOMEvent', this).call(this); - - this.on('click .te-table-add-row', function () { - return _this2.eventManager.emit('command', 'AddRow'); - }); - this.on('click .te-table-add-col', function () { - return _this2.eventManager.emit('command', 'AddCol'); - }); - this.on('click .te-table-col-align-left', function () { - return _this2.eventManager.emit('command', 'AlignCol', 'left'); - }); - this.on('click .te-table-col-align-center', function () { - return _this2.eventManager.emit('command', 'AlignCol', 'center'); - }); - this.on('click .te-table-col-align-right', function () { - return _this2.eventManager.emit('command', 'AlignCol', 'right'); - }); - this.on('click .te-table-remove-col', function () { - return _this2.eventManager.emit('command', 'RemoveCol'); - }); - this.on('click .te-table-remove', function () { - return _this2.eventManager.emit('command', 'RemoveTable'); - }); - this._bindClickEventOnRemoveRowMenu(); - } - - /** - * bind editor events - * @private - * @override - */ - - }, { - key: '_initEditorEvent', - value: function _initEditorEvent() { - var _this3 = this; - - _get(PopupTableUtils.prototype.__proto__ || Object.getPrototypeOf(PopupTableUtils.prototype), '_initEditorEvent', this).call(this); - - this.eventManager.listen('focus', function () { - return _this3.hide(); - }); - this.eventManager.listen('mousedown', function () { - return _this3.hide(); - }); - this.eventManager.listen('closeAllPopup', function () { - return _this3.hide(); - }); - this.eventManager.listen('openPopupTableUtils', function (ev) { - var offset = _this3.$el.parent().offset(); - var x = ev.clientX - offset.left; - var y = ev.clientY - offset.top + (0, _jquery2.default)(window).scrollTop(); - - _this3._disableRemoveRowMenu(ev.target); - - _this3.$el.css({ - position: 'absolute', - top: y + 5, // beside mouse pointer - left: x + 10 - }); - _this3.eventManager.emit('closeAllPopup'); - _this3.show(); - }); - } - }, { - key: '_bindClickEventOnRemoveRowMenu', - value: function _bindClickEventOnRemoveRowMenu() { - var _this4 = this; - - this.on('click .' + REMOVE_ROW_MENU_CLASS_NAME, function (ev) { - var target = ev.target; - - - if ((0, _jquery2.default)(target).hasClass(DISABLED_MENU_CLASS_NAME)) { - ev.preventDefault(); - } else { - _this4.eventManager.emit('command', 'RemoveRow'); - } - }); - } - }, { - key: '_disableRemoveRowMenu', - value: function _disableRemoveRowMenu(target) { - var $menu = this.$el.find('.' + REMOVE_ROW_MENU_CLASS_NAME); - - if (target.nodeName === 'TH') { - $menu.addClass(DISABLED_MENU_CLASS_NAME); - } else { - $menu.removeClass(DISABLED_MENU_CLASS_NAME); - } - } - }]); - - return PopupTableUtils; -}(_layerpopup2.default); - -exports.default = PopupTableUtils; - -/***/ }), -/* 105 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _layerpopup = __webpack_require__(7); - -var _layerpopup2 = _interopRequireDefault(_layerpopup); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements PopupAddTable - * @author NHN FE Development Lab - */ - - -var CLASS_TABLE_SELECTION = 'te-table-selection'; -var CLASS_TABLE_HEADER = 'te-table-header'; -var CLASS_TABLE_BODY = 'te-table-body'; -var CLASS_SELECTION_AREA = 'te-selection-area'; -var CLASS_DESCRIPTION = 'te-description'; - -var POPUP_CONTENT = '\n
    \n
    \n
    \n
    \n
    \n

    \n'; - -var CELL_WIDTH = 25; -var CELL_HEIGHT = 17; -var MIN_ROW_INDEX = 7; -var MAX_ROW_INDEX = 14; -var MIN_COL_INDEX = 5; -var MAX_COL_INDEX = 9; -var MIN_ROW_SELECTION_INDEX = 1; -var MIN_COL_SELECTION_INDEX = 1; -var HEADER_ROW_COUNT = 1; -var LAST_BORDER = 1; - -/** - * Class PopupAddTable - * It implements Popup to add a table - * @param {LayerPopupOption} options - layer popup option - * @ignore - */ - -var PopupAddTable = function (_LayerPopup) { - _inherits(PopupAddTable, _LayerPopup); - - /** - * Toolbar Button which the Popup is bound to. - * @type {jQuery} - * @private - */ - function PopupAddTable(options) { - _classCallCheck(this, PopupAddTable); - - options = _tuiCodeSnippet2.default.extend({ - header: false, - className: 'te-popup-add-table', - content: POPUP_CONTENT - }, options); - return _possibleConstructorReturn(this, (PopupAddTable.__proto__ || Object.getPrototypeOf(PopupAddTable)).call(this, options)); - } - - /** - * init instance. - * store properties & prepare before initialize DOM - * @param {LayerPopupOption} options - layer popup options - * @private - * @override - */ - - - /** - * EventManager instance - * @type {EventManager} - * @private - */ - - - _createClass(PopupAddTable, [{ - key: '_initInstance', - value: function _initInstance(options) { - _get(PopupAddTable.prototype.__proto__ || Object.getPrototypeOf(PopupAddTable.prototype), '_initInstance', this).call(this, options); - - this._selectedBound = {}; - this._tableBound = {}; - this._eventManager = options.eventManager; - this._$button = options.$button; - } - - /** - * initialize DOM, render popup - * @private - * @override - */ - - }, { - key: '_initDOM', - value: function _initDOM() { - _get(PopupAddTable.prototype.__proto__ || Object.getPrototypeOf(PopupAddTable.prototype), '_initDOM', this).call(this); - - this._cacheElements(); - this._setTableSizeByBound(MIN_COL_INDEX, MIN_ROW_INDEX); - } - - /** - * bind DOM events - * @private - * @override - */ - - }, { - key: '_initDOMEvent', - value: function _initDOMEvent(options) { - var _this2 = this; - - _get(PopupAddTable.prototype.__proto__ || Object.getPrototypeOf(PopupAddTable.prototype), '_initDOMEvent', this).call(this, options); - - this.on('mousemove .' + CLASS_TABLE_SELECTION, function (ev) { - var x = ev.pageX - _this2._selectionOffset.left; - var y = ev.pageY - _this2._selectionOffset.top; - var bound = _this2._getSelectionBoundByOffset(x, y); - - _this2._resizeTableBySelectionIfNeed(bound.col, bound.row); - - _this2._setSelectionAreaByBound(bound.col, bound.row); - _this2._setDisplayText(bound.col, bound.row); - _this2._setSelectedBound(bound.col, bound.row); - }); - - this.on('click .' + CLASS_TABLE_SELECTION, function () { - var tableSize = _this2._getSelectedTableSize(); - _this2._eventManager.emit('command', 'Table', tableSize.col, tableSize.row); - }); - } - - /** - * bind editor events - * @private - * @override - */ - - }, { - key: '_initEditorEvent', - value: function _initEditorEvent() { - var _this3 = this; - - _get(PopupAddTable.prototype.__proto__ || Object.getPrototypeOf(PopupAddTable.prototype), '_initEditorEvent', this).call(this); - - this._eventManager.listen('focus', function () { - return _this3.hide(); - }); - this._eventManager.listen('closeAllPopup', function () { - return _this3.hide(); - }); - - this._eventManager.listen('openPopupAddTable', function () { - var $button = _this3._$button; - - var _$button$get = $button.get(0), - offsetTop = _$button$get.offsetTop, - offsetLeft = _$button$get.offsetLeft; - - _this3.$el.css({ - top: offsetTop + $button.outerHeight(), - left: offsetLeft - }); - _this3._eventManager.emit('closeAllPopup'); - _this3.show(); - _this3._selectionOffset = _this3.$el.find('.' + CLASS_TABLE_SELECTION).offset(); - }); - } - - /** - * Cache elements for use - * @private - */ - - }, { - key: '_cacheElements', - value: function _cacheElements() { - this.$header = this.$el.find('.' + CLASS_TABLE_HEADER); - this.$body = this.$el.find('.' + CLASS_TABLE_BODY); - this.$selection = this.$el.find('.' + CLASS_SELECTION_AREA); - this.$desc = this.$el.find('.' + CLASS_DESCRIPTION); - } - - /** - * Resize table if need - * @param {number} col column index - * @param {number} row row index - * @private - */ - - }, { - key: '_resizeTableBySelectionIfNeed', - value: function _resizeTableBySelectionIfNeed(col, row) { - var resizedBound = this._getResizedTableBound(col, row); - - if (resizedBound) { - this._setTableSizeByBound(resizedBound.col, resizedBound.row); - } - } - - /** - * Get resized table bound if Need - * @param {number} col column index - * @param {number} row row index - * @returns {object} bound - * @private - */ - - }, { - key: '_getResizedTableBound', - value: function _getResizedTableBound(col, row) { - var resizedCol = void 0, - resizedRow = void 0, - resizedBound = void 0; - - if (col >= MIN_COL_INDEX && col < MAX_COL_INDEX) { - resizedCol = col + 1; - } else if (col < MIN_COL_INDEX) { - resizedCol = MIN_COL_INDEX; - } - - if (row >= MIN_ROW_INDEX && row < MAX_ROW_INDEX) { - resizedRow = row + 1; - } else if (row < MIN_ROW_INDEX) { - resizedRow = MIN_ROW_INDEX; - } - - if (this._isNeedResizeTable(resizedCol, resizedRow)) { - resizedBound = { - row: resizedRow || this._tableBound.row, - col: resizedCol || this._tableBound.col - }; - } - - return resizedBound; - } - - /** - * check if need resize table - * @param {number} col column index - * @param {number} row row index - * @returns {boolean} result - * @private - */ - - }, { - key: '_isNeedResizeTable', - value: function _isNeedResizeTable(col, row) { - return col && col !== this._tableBound.col || row && row !== this._tableBound.row; - } - - /** - * Get bound by offset - * @param {number} x offset - * @param {number} y offset - * @returns {object} bound - * @private - */ - - }, { - key: '_getBoundByOffset', - value: function _getBoundByOffset(x, y) { - var row = parseInt(y / CELL_HEIGHT, 10); - var col = parseInt(x / CELL_WIDTH, 10); - - return { - row: row, - col: col - }; - } - - /** - * Get offset by bound - * @param {number} col column index - * @param {number} row row index - * @returns {object} offset - * @private - */ - - }, { - key: '_getOffsetByBound', - value: function _getOffsetByBound(col, row) { - var x = col * CELL_WIDTH + CELL_WIDTH, - y = row * CELL_HEIGHT + CELL_HEIGHT; - - return { - x: x, - y: y - }; - } - - /** - * Set table size with bound - * @param {number} col column index - * @param {number} row row index - * @private - */ - - }, { - key: '_setTableSizeByBound', - value: function _setTableSizeByBound(col, row) { - var boundOffset = this._getOffsetByBound(col, row - HEADER_ROW_COUNT); - this._setTableSize(boundOffset.x, boundOffset.y); - this._tableBound.row = row; - this._tableBound.col = col; - } - - /** - * Get selection bound that process with range by offset - * @param {number} x offset - * @param {number} y offset - * @returns {object} bound - * @private - */ - - }, { - key: '_getSelectionBoundByOffset', - value: function _getSelectionBoundByOffset(x, y) { - var bound = this._getBoundByOffset(x, y); - - if (bound.row < MIN_ROW_SELECTION_INDEX) { - bound.row = MIN_ROW_SELECTION_INDEX; - } else if (bound.row > this._tableBound.row) { - bound.row = this._tableBound.row; - } - - if (bound.col < MIN_COL_SELECTION_INDEX) { - bound.col = MIN_COL_SELECTION_INDEX; - } else if (bound.col > this._tableBound.col) { - bound.col = this._tableBound.col; - } - - return bound; - } - - /** - * Set selection area with bound - * @param {number} col column index - * @param {number} row row index - * @private - */ - - }, { - key: '_setSelectionAreaByBound', - value: function _setSelectionAreaByBound(col, row) { - var boundOffset = this._getOffsetByBound(col, row); - this._setSelectionArea(boundOffset.x, boundOffset.y); - } - - /** - * Set selected bound - * @param {number} col column index - * @param {number} row row index - * @private - */ - - }, { - key: '_setSelectedBound', - value: function _setSelectedBound(col, row) { - this._selectedBound.col = col; - this._selectedBound.row = row; - } - - /** - * Get selected table size - * @returns {object} bound - * @private - */ - - }, { - key: '_getSelectedTableSize', - value: function _getSelectedTableSize() { - return { - row: this._selectedBound.row + 1, - col: this._selectedBound.col + 1 - }; - } - - /** - * Set selected table size text for display - * @param {number} col column index - * @param {number} row row index - * @private - */ - - }, { - key: '_setDisplayText', - value: function _setDisplayText(col, row) { - this.$desc.html(col + 1 + ' x ' + (row + 1)); - } - - /** - * Set table element size - * @param {number} x offset - * @param {number} y offset - * @private - */ - - }, { - key: '_setTableSize', - value: function _setTableSize(x, y) { - x += LAST_BORDER; - y += LAST_BORDER; - - this.$header.css({ - height: CELL_HEIGHT, - width: x - }); - - this.$body.css({ - height: y, - width: x - }); - - this.$el.css({ - width: x + 30 - }); - } - - /** - * Set selection element size - * @param {number} x offset - * @param {number} y offset - * @private - */ - - }, { - key: '_setSelectionArea', - value: function _setSelectionArea(x, y) { - x += LAST_BORDER; - y += LAST_BORDER; - - this.$selection.css({ - height: y, - width: x - }); - } - }]); - - return PopupAddTable; -}(_layerpopup2.default); - -PopupAddTable.CELL_WIDTH = CELL_WIDTH; -PopupAddTable.CELL_HEIGHT = CELL_HEIGHT; -PopupAddTable.MIN_ROW_SELECTION_INDEX = MIN_ROW_SELECTION_INDEX; -PopupAddTable.MIN_COL_SELECTION_INDEX = MIN_COL_SELECTION_INDEX; - -exports.default = PopupAddTable; - -/***/ }), -/* 106 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _layerpopup = __webpack_require__(7); - -var _layerpopup2 = _interopRequireDefault(_layerpopup); - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements PopupAddHeading - * @author NHN FE Development Lab - */ - - -/** - * Class PopupAddHeading - * It implements Popup to add headings - * @param {LayerPopupOption} options - layer popup option - * @ignore - */ -var PopupAddHeading = function (_LayerPopup) { - _inherits(PopupAddHeading, _LayerPopup); - - function PopupAddHeading(options) { - _classCallCheck(this, PopupAddHeading); - - var POPUP_CONTENT = '\n
      \n
    • ' + _i18n2.default.get('Heading') + ' 1

    • \n
    • ' + _i18n2.default.get('Heading') + ' 2

    • \n
    • ' + _i18n2.default.get('Heading') + ' 3

    • \n
    • ' + _i18n2.default.get('Heading') + ' 4

    • \n
    • ' + _i18n2.default.get('Heading') + ' 5
    • \n
    • ' + _i18n2.default.get('Heading') + ' 6
    • \n
    • ' + _i18n2.default.get('Paragraph') + '
    • \n
    \n '; - options = _tuiCodeSnippet2.default.extend({ - header: false, - className: 'te-heading-add', - content: POPUP_CONTENT - }, options); - return _possibleConstructorReturn(this, (PopupAddHeading.__proto__ || Object.getPrototypeOf(PopupAddHeading)).call(this, options)); - } - - /** - * init instance. - * store properties & prepare before initialize DOM - * @param {LayerPopupOption} options - layer popup options - * @private - * @override - */ - - - _createClass(PopupAddHeading, [{ - key: '_initInstance', - value: function _initInstance(options) { - _get(PopupAddHeading.prototype.__proto__ || Object.getPrototypeOf(PopupAddHeading.prototype), '_initInstance', this).call(this, options); - - this._eventManager = options.eventManager; - this._$button = options.$button; - } - - /** - * bind DOM events - * @private - * @override - */ - - }, { - key: '_initDOMEvent', - value: function _initDOMEvent() { - var _this2 = this; - - _get(PopupAddHeading.prototype.__proto__ || Object.getPrototypeOf(PopupAddHeading.prototype), '_initDOMEvent', this).call(this); - - this.on('click li', function (ev) { - var $li = (0, _jquery2.default)(ev.target).closest('li'); - _this2._eventManager.emit('command', $li.data('type'), $li.data('value')); - }); - } - - /** - * bind editor events - * @private - * @override - */ - - }, { - key: '_initEditorEvent', - value: function _initEditorEvent() { - var _this3 = this; - - _get(PopupAddHeading.prototype.__proto__ || Object.getPrototypeOf(PopupAddHeading.prototype), '_initEditorEvent', this).call(this); - - this._eventManager.listen('focus', this.hide.bind(this)); - this._eventManager.listen('closeAllPopup', this.hide.bind(this)); - this._eventManager.listen('openHeadingSelect', function () { - var $button = _this3._$button; - - var _$button$get = $button.get(0), - offsetTop = _$button$get.offsetTop, - offsetLeft = _$button$get.offsetLeft; - - _this3.$el.css({ - top: offsetTop + $button.outerHeight(), - left: offsetLeft - }); - - _this3._eventManager.emit('closeAllPopup'); - _this3.show(); - }); - } - }]); - - return PopupAddHeading; -}(_layerpopup2.default); - -exports.default = PopupAddHeading; - -/***/ }), -/* 107 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _layerpopup = __webpack_require__(7); - -var _layerpopup2 = _interopRequireDefault(_layerpopup); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements popup code block languages - * @author NHN FE Development Lab - */ - - -var BUTTON_CLASS_PREFIX = 'te-popup-code-block-lang-'; - -/** - * Class Popup code block languages select list - * @param {LayerPopupOption} options - layer popup option - * @ignore - */ - -var PopupCodeBlockLanguages = function (_LayerPopup) { - _inherits(PopupCodeBlockLanguages, _LayerPopup); - - function PopupCodeBlockLanguages(options) { - _classCallCheck(this, PopupCodeBlockLanguages); - - var popupButtonsHTML = []; - var _options = options, - languages = _options.languages; - - languages.forEach(function (lang) { - return popupButtonsHTML.push(''); - }); - - options = _tuiCodeSnippet2.default.extend({ - header: false, - className: 'te-popup-code-block-languages', - content: popupButtonsHTML.join('') - }, options); - return _possibleConstructorReturn(this, (PopupCodeBlockLanguages.__proto__ || Object.getPrototypeOf(PopupCodeBlockLanguages)).call(this, options)); - } - - /** - * init instance. - * store properties & prepare before initialize DOM - * @param {LayerPopupOption} options - layer popup options - * @private - * @override - */ - - - _createClass(PopupCodeBlockLanguages, [{ - key: '_initInstance', - value: function _initInstance(options) { - _get(PopupCodeBlockLanguages.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockLanguages.prototype), '_initInstance', this).call(this, options); - - this._onSelectedLanguage = null; - this._onDismissed = null; - this._currentButton = null; - this._$buttons = null; - this._languages = options.languages; - - this.eventManager = options.eventManager; - } - - /** - * initialize DOM, render popup - * @private - * @override - */ - - }, { - key: '_initDOM', - value: function _initDOM(options) { - _get(PopupCodeBlockLanguages.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockLanguages.prototype), '_initDOM', this).call(this, options); - - this.$el.css('z-index', 10000); - - this._$buttons = this.$el.find('button'); - this._activateButtonByIndex(0); - } - - /** - * bind DOM events - * @private - * @override - */ - - }, { - key: '_initDOMEvent', - value: function _initDOMEvent() { - var _this2 = this; - - _get(PopupCodeBlockLanguages.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockLanguages.prototype), '_initDOMEvent', this).call(this); - - var handler = function handler(event) { - var language = (0, _jquery2.default)(event.target).data('lang'); - if (_this2._onSelectedLanguage) { - _this2._onSelectedLanguage(language); - } - _this2.hide(); - }; - this._languages.forEach(function (lang) { - return _this2.on('mousedown .' + BUTTON_CLASS_PREFIX + lang, handler); - }); - } - - /** - * bind editor events - * @private - * @override - */ - - }, { - key: '_initEditorEvent', - value: function _initEditorEvent() { - var _this3 = this; - - _get(PopupCodeBlockLanguages.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockLanguages.prototype), '_initEditorEvent', this).call(this); - - this.eventManager.listen('openPopupCodeBlockLanguages', function (data) { - _this3.show(data.callback); - var elementStyle = _this3.$el.get(0).style; - elementStyle.top = data.offset.top + 'px'; - elementStyle.left = data.offset.left + 'px'; - _this3.setCurrentLanguage(data.language); - - return _this3; - }); - this.eventManager.listen('focus', function () { - return _this3.hide(); - }); - this.eventManager.listen('mousedown', function () { - return _this3.hide(); - }); - this.eventManager.listen('closeAllPopup', function () { - return _this3.hide(); - }); - this.eventManager.listen('closePopupCodeBlockLanguages', function () { - return _this3.hide(); - }); - this.eventManager.listen('scroll', function () { - return _this3.hide(); - }); - } - - /** - * activate an item by index - * @param {number} index - item index - * @private - */ - - }, { - key: '_activateButtonByIndex', - value: function _activateButtonByIndex(index) { - if (this._currentButton) { - (0, _jquery2.default)(this._currentButton).removeClass('active'); - } - this._currentButton = this._$buttons.get(index); - (0, _jquery2.default)(this._currentButton).addClass('active'); - this._currentButton.scrollIntoView(); - } - - /** - * move to prev language - */ - - }, { - key: 'prev', - value: function prev() { - var index = this._$buttons.index(this._currentButton) - 1; - if (index < 0) { - index = this._$buttons.length - 1; - } - this._activateButtonByIndex(index); - } - - /** - * move to next language - */ - - }, { - key: 'next', - value: function next() { - var index = this._$buttons.index(this._currentButton) + 1; - if (index >= this._$buttons.length) { - index = 0; - } - this._activateButtonByIndex(index); - } - - /** - * current language - * @returns {string} language - */ - - }, { - key: 'getCurrentLanguage', - value: function getCurrentLanguage() { - var language = (0, _jquery2.default)(this._currentButton).data('lang'); - - return language; - } - - /** - * set current language - * @param {string} language - current language - */ - - }, { - key: 'setCurrentLanguage', - value: function setCurrentLanguage(language) { - var item = this._$buttons.filter('.' + BUTTON_CLASS_PREFIX + language); - if (item.length > 0) { - var index = this._$buttons.index(item); - this._activateButtonByIndex(index); - } - } - - /** - * show popup - * @param {object} callback - to be called on language selected & dismissed - * @override - */ - - }, { - key: 'show', - value: function show(callback) { - this._onSelectedLanguage = callback.selected; - this._onDismissed = callback.dismissed; - _get(PopupCodeBlockLanguages.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockLanguages.prototype), 'show', this).call(this); - } - - /** - * hide popup - * @override - */ - - }, { - key: 'hide', - value: function hide() { - if (this._onDismissed) { - this._onDismissed(); - } - this._onSelectedLanguage = null; - this._onDismissed = null; - _get(PopupCodeBlockLanguages.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockLanguages.prototype), 'hide', this).call(this); - } - }]); - - return PopupCodeBlockLanguages; -}(_layerpopup2.default); - -exports.default = PopupCodeBlockLanguages; - -/***/ }), -/* 108 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _layerpopup = __webpack_require__(7); - -var _layerpopup2 = _interopRequireDefault(_layerpopup); - -var _scrollSyncSplit = __webpack_require__(109); - -var _scrollSyncSplit2 = _interopRequireDefault(_scrollSyncSplit); - -var _codeBlockEditor = __webpack_require__(110); - -var _codeBlockEditor2 = _interopRequireDefault(_codeBlockEditor); - -var _codeBlockPreview = __webpack_require__(111); - -var _codeBlockPreview2 = _interopRequireDefault(_codeBlockPreview); - -var _codeBlockLanguagesCombo = __webpack_require__(112); - -var _codeBlockLanguagesCombo2 = _interopRequireDefault(_codeBlockLanguagesCombo); - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements popup code block editor - * @author NHN FE Development Lab - */ - - -var CLASS_PREFIX = 'popup-editor-'; -var CLASS_OK_BUTTON = 'te-ok-button'; -var CLASS_CLOSE_BUTTON = 'te-close-button'; -var CLASS_POPUP_CLOSE_BUTTON = 'tui-popup-close-button'; -var TEMPLATE_HEADER_BUTTONS = '\n \n \n \n \n'; - -/** - * Class popup code block editor - * @param {LayerPopupOption} options - layer popup option - * @ignore - */ - -var PopupCodeBlockEditor = function (_LayerPopup) { - _inherits(PopupCodeBlockEditor, _LayerPopup); - - function PopupCodeBlockEditor(options) { - _classCallCheck(this, PopupCodeBlockEditor); - - var TEMPLATE_CONTENT = '\n
    \n
    \n \n \n
    \n '; - options = _tuiCodeSnippet2.default.extend({ - header: true, - title: 'CodeBlock Editor', - content: TEMPLATE_CONTENT, - className: 'tui-popup-code-block-editor', - headerButtons: TEMPLATE_HEADER_BUTTONS, - modal: true - }, options); - return _possibleConstructorReturn(this, (PopupCodeBlockEditor.__proto__ || Object.getPrototypeOf(PopupCodeBlockEditor)).call(this, options)); - } - - /** - * init instance. - * store properties & prepare before initialize DOM - * @param {LayerPopupOption} options - layer popup options - * @private - * @override - */ - - - _createClass(PopupCodeBlockEditor, [{ - key: '_initInstance', - value: function _initInstance(options) { - _get(PopupCodeBlockEditor.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockEditor.prototype), '_initInstance', this).call(this, options); - - this.eventManager = options.eventManager; - this.convertor = options.convertor; - } - - /** - * initialize DOM, render popup - * @private - * @override - */ - - }, { - key: '_initDOM', - value: function _initDOM(options) { - _get(PopupCodeBlockEditor.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockEditor.prototype), '_initDOM', this).call(this, options); - - var el = this.$el.get(0); - this._body = el.querySelector('.' + CLASS_PREFIX + 'body'); - this._toggleFitButton = el.querySelector('.' + CLASS_PREFIX + 'toggle-fit'); - this._togglePreviewButton = el.querySelector('.' + CLASS_PREFIX + 'toggle-preview'); - this._toggleScrollButton = el.querySelector('.' + CLASS_PREFIX + 'toggle-scroll'); - this._okButton = el.querySelector('.' + CLASS_OK_BUTTON); - this._closeButton = el.querySelector('.' + CLASS_CLOSE_BUTTON); - - this._codeMirrorWrapper = this._createCodeBlockEditor(); - this._previewWrapper = this._createPreview(); - this._scrollSyncSplit = new _scrollSyncSplit2.default(this._body, this._codeMirrorWrapper, this._previewWrapper); - - this._updateFitWindowButton(); - this._updatePreviewButton(); - this._updateScrollButton(); - - this._codeBlockLanguagesCombo = this._createCodeBlockLanguagesCombo(); - } - - /** - * bind DOM events - * @private - * @override - */ - - }, { - key: '_initDOMEvent', - value: function _initDOMEvent() { - var _this2 = this; - - _get(PopupCodeBlockEditor.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockEditor.prototype), '_initDOMEvent', this).call(this); - - this.on('scroll', function (ev) { - return ev.preventDefault(); - }); - this.on('click .' + CLASS_PREFIX + 'toggle-fit', function () { - return _this2._toggleFitToWindow(); - }); - this.on('click .' + CLASS_PREFIX + 'toggle-preview', function () { - return _this2._togglePreview(); - }); - this.on('click .' + CLASS_PREFIX + 'toggle-scroll', function () { - return _this2._toggleScroll(); - }); - this.on('click .' + CLASS_OK_BUTTON, function () { - return _this2._save(); - }); - this.on('click .' + CLASS_CLOSE_BUTTON, function () { - return _this2.hide(); - }); - this.on('click .' + CLASS_PREFIX + 'close', function () { - return _this2.hide(); - }); - this.on('click .' + CLASS_PREFIX + 'editor-wrapper', function (ev) { - if (ev.target === _this2._codeMirrorWrapper) { - _this2._focusEditor(true); - } - }); - } - - /** - * bind editor events - * @private - * @override - */ - - }, { - key: '_initEditorEvent', - value: function _initEditorEvent() { - var _this3 = this; - - _get(PopupCodeBlockEditor.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockEditor.prototype), '_initEditorEvent', this).call(this); - - this.eventManager.listen('openPopupCodeBlockEditor', function (codeBlockElement) { - _this3.eventManager.emit('closeAllPopup'); - _this3.show(codeBlockElement); - - return _this3; - }); - this.eventManager.listen('closeAllPopup', this.hide.bind(this)); - this.eventManager.listen('closePopupCodeBlockEditor', this.hide.bind(this)); - } - }, { - key: '_createCodeBlockEditor', - value: function _createCodeBlockEditor() { - var codeMirrorWrapper = document.createElement('div'); - codeMirrorWrapper.className = CLASS_PREFIX + 'editor-wrapper'; - - this._codeBlockEditor = new _codeBlockEditor2.default(codeMirrorWrapper, this.eventManager); - - return codeMirrorWrapper; - } - }, { - key: '_createPreview', - value: function _createPreview() { - var previewWrapper = document.createElement('div'); - this._codeBlockPreview = new _codeBlockPreview2.default((0, _jquery2.default)(previewWrapper), this.eventManager, this.convertor, this._codeBlockEditor); - - return previewWrapper; - } - }, { - key: '_createCodeBlockLanguagesCombo', - value: function _createCodeBlockLanguagesCombo() { - var _this4 = this; - - var titleElement = this.getTitleElement(); - var codeBlockLanguagesCombo = new _codeBlockLanguagesCombo2.default(this.eventManager); - - codeBlockLanguagesCombo.setOnLanguageSelected(function (selectedLanguage) { - _this4._codeBlockEditor.setLanguage(selectedLanguage); - _this4._codeBlockEditor.refresh(); - _this4._focusEditor(); - }); - - titleElement.innerHTML = 'CodeBlock Editor'; - titleElement.appendChild(codeBlockLanguagesCombo.getElement()); - - return codeBlockLanguagesCombo; - } - }, { - key: '_updateFitWindowButton', - value: function _updateFitWindowButton() { - (0, _jquery2.default)(this._toggleFitButton).toggleClass('active', this.isFitToWindow()); - } - }, { - key: '_updatePreviewButton', - value: function _updatePreviewButton() { - (0, _jquery2.default)(this._togglePreviewButton).toggleClass('active', this._scrollSyncSplit.isSplitView()); - } - }, { - key: '_updateScrollButton', - value: function _updateScrollButton() { - if (this._scrollSyncSplit.isSplitView()) { - this._toggleScrollButton.style.display = 'inline-block'; - } else { - this._toggleScrollButton.style.display = 'none'; - } - (0, _jquery2.default)(this._toggleScrollButton).toggleClass('active', this._scrollSyncSplit.isScrollSynced()); - } - }, { - key: '_focusEditor', - value: function _focusEditor(cursorToEnd) { - this._codeBlockEditor.focus(); - if (cursorToEnd) { - this._codeBlockEditor.moveCursorToEnd(); - } else { - this._codeBlockEditor.moveCursorToStart(); - } - } - }, { - key: '_togglePreview', - value: function _togglePreview() { - this._scrollSyncSplit.toggleSplitView(); - this._updatePreviewButton(); - this._updateScrollButton(); - this._codeBlockEditor.refresh(); - } - }, { - key: '_toggleFitToWindow', - value: function _toggleFitToWindow() { - this.toggleFitToWindow(); - this._updateFitWindowButton(); - this._codeBlockEditor.refresh(); - } - }, { - key: '_toggleScroll', - value: function _toggleScroll() { - this._scrollSyncSplit.toggleScrollSync(); - this._updateScrollButton(); - } - - /** - * store code mirror text to wysiwyg code block - * @private - */ - - }, { - key: '_save', - value: function _save() { - this._codeBlockEditor.save(this._codeBlockElement); - this.hide(); - } - - /** - * load code mirror text from wysiwyg code block - * @param {HTMLElement} codeBlockElement - code block element instance to load code from - * @private - */ - - }, { - key: '_load', - value: function _load(codeBlockElement) { - this._codeBlockElement = codeBlockElement; - this._codeBlockEditor.load(codeBlockElement); - this._codeBlockLanguagesCombo.setLanguage(this._codeBlockEditor.getLanguage()); - this._focusEditor(); - this._codeBlockPreview.refresh(); - } - - /** - * show popup - * @param {HTMLElement} codeBlockElement - code block element - * @override - */ - - }, { - key: 'show', - value: function show(codeBlockElement) { - _get(PopupCodeBlockEditor.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockEditor.prototype), 'show', this).call(this); - - if (!codeBlockElement) { - throw new Error('should be called with codeBlockElement'); - } - this._load(codeBlockElement); - } - - /** - * hide popup - * @override - */ - - }, { - key: 'hide', - value: function hide() { - this.setFitToWindow(false); - - if (this._codeBlockEditor) { - this._codeBlockEditor.clear(); - } - if (this._codeBlockPreview) { - this._codeBlockPreview.clear(); - } - this._codeBlockElement = null; - - _get(PopupCodeBlockEditor.prototype.__proto__ || Object.getPrototypeOf(PopupCodeBlockEditor.prototype), 'hide', this).call(this); - } - }]); - - return PopupCodeBlockEditor; -}(_layerpopup2.default); - -exports.default = PopupCodeBlockEditor; - -/***/ }), -/* 109 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview Implements scroll sync split - * @author NHN FE Development Lab - */ - - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var CLASS_SPLIT_SCROLL = 'tui-split-scroll'; -var CLASS_SINGLE_CONTENT = 'single-content'; -var CLASS_SCROLL_SYNC = 'scroll-sync'; -var CLASS_SCROLL_WRAPPER = 'tui-split-scroll-wrapper'; -var CLASS_SCROLL_CONTENT = 'tui-split-scroll-content'; -var CLASS_SPLITTER = 'tui-splitter'; -var EVENT_REQUIRE_SCROLL_SYNC = 'requireScrollSync'; -var EVENT_REQUIRE_SCROLL_INTO_VIEW = 'requireScrollIntoView'; -var CLASS_CONTENT_LEFT = 'tui-split-content-left'; -var CLASS_CONTENT_RIGHT = 'tui-split-content-right'; -var CLASS_CONTENT = { - 'left': CLASS_CONTENT_LEFT, - 'right': CLASS_CONTENT_RIGHT -}; - -/** - * Class ScrollSyncSplit - * @param {Element} baseElement - an element which attach a splitSyncSplit - * @param {Element} leftElement - an element to be on left side split view - * @param {Element} rightElement - an element to be on right side split view - * @param {object} options - options - * @param {boolean} [options.showScrollSyncButton=false] - show scroll sync button on top right corner - * @param {boolean} [options.scrollSync=true] - true for enable scroll sync - * @param {boolean} [options.splitView=true] - true for split, false for single view - * @ignore - */ - -var ScrollSyncSplit = function () { - function ScrollSyncSplit(baseElement, leftElement, rightElement) { - var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; - - _classCallCheck(this, ScrollSyncSplit); - - options = _tuiCodeSnippet2.default.extend({ - showScrollSyncButton: false, - scrollSync: true, - splitView: true - }, options); - this._baseElement = baseElement; - - /** - * left, right side content elements - * @type {HTMLElement[]} - * @private - */ - this._contentElements = []; - - this._initDom(leftElement, rightElement, options); - this._initDomEvent(); - } - - _createClass(ScrollSyncSplit, [{ - key: '_initDom', - value: function _initDom(leftElement, rightElement, options) { - var el = document.createElement('div'); - el.className = CLASS_SPLIT_SCROLL; - this._el = el; - - var scrollWrapper = document.createElement('div'); - scrollWrapper.className = CLASS_SCROLL_WRAPPER; - this._scrollWrapper = scrollWrapper; - this._setScrollSync(options.scrollSync); - this.setSplitView(options.splitView); - - var contentWrapper = document.createElement('div'); - contentWrapper.className = CLASS_SCROLL_CONTENT; - this._contentWrapper = contentWrapper; - - var splitter = document.createElement('div'); - splitter.className = CLASS_SPLITTER; - - this._baseElement.appendChild(el); - el.appendChild(scrollWrapper); - scrollWrapper.appendChild(contentWrapper); - scrollWrapper.appendChild(splitter); - this._setLeft(leftElement); - this._setRight(rightElement); - } - }, { - key: '_initDomEvent', - value: function _initDomEvent() { - this._contentWrapper.addEventListener('scroll', this.sync.bind(this)); - } - }, { - key: '_requireScrollIntoView', - value: function _requireScrollIntoView(event) { - var element = event.target; - - var _element$getBoundingC = element.getBoundingClientRect(), - targetTop = _element$getBoundingC.top, - targetBottom = _element$getBoundingC.bottom; - - var wrapperTop = void 0, - wrapperBottom = void 0, - wrapperElement = void 0; - - if (this.isScrollSynced()) { - wrapperElement = this._contentWrapper; - } else if ((0, _jquery2.default)(element).parents(this._contentElements.left).length) { - wrapperElement = this._contentElements.left; - } else if ((0, _jquery2.default)(element).parents(this._contentElements.right).length) { - wrapperElement = this._contentElements.right; - } else { - return; - } - - var _wrapperElement$getBo = wrapperElement.getBoundingClientRect(); - - wrapperTop = _wrapperElement$getBo.top; - wrapperBottom = _wrapperElement$getBo.bottom; - - - if (targetTop < wrapperTop) { - wrapperElement.scrollTop = wrapperElement.scrollTop + targetTop - wrapperTop; - } else if (targetBottom > wrapperBottom) { - wrapperElement.scrollTop = wrapperElement.scrollTop + targetBottom - wrapperBottom; - } - - this.sync(); - } - - /** - * set content element for given side - * @param {Element} element - content element - * @param {string} side - 'left' | 'right' - * @private - */ - - }, { - key: '_setContentElement', - value: function _setContentElement(element, side) { - var _this = this; - - var contentElement = this._contentElements[side]; - - if (contentElement) { - (0, _jquery2.default)(contentElement).off(EVENT_REQUIRE_SCROLL_INTO_VIEW); - this._contentWrapper.removeChild(contentElement); - } - (0, _jquery2.default)(element).addClass(CLASS_CONTENT[side]); - this._contentWrapper.appendChild(element); - (0, _jquery2.default)(element).on(EVENT_REQUIRE_SCROLL_INTO_VIEW, function (ev) { - return _this._requireScrollIntoView(ev); - }); - (0, _jquery2.default)(element).on(EVENT_REQUIRE_SCROLL_SYNC, function () { - return _this.sync(); - }); - - this._contentElements[side] = element; - - this.sync(); - } - - /** - * set left side element - * @param {Element} element - an element to be on left side split view - * @private - */ - - }, { - key: '_setLeft', - value: function _setLeft(element) { - this._setContentElement(element, 'left'); - } - - /** - * set right side element - * @param {Element} element - an element to be on right side split view - * @private - */ - - }, { - key: '_setRight', - value: function _setRight(element) { - this._setContentElement(element, 'right'); - } - }, { - key: '_setScrollSync', - value: function _setScrollSync(activate) { - (0, _jquery2.default)(this._el).toggleClass(CLASS_SCROLL_SYNC, activate); - } - - /** - * toggle multi scroll - */ - - }, { - key: 'toggleScrollSync', - value: function toggleScrollSync() { - (0, _jquery2.default)(this._el).toggleClass(CLASS_SCROLL_SYNC); - } - }, { - key: 'setSplitView', - value: function setSplitView(activate) { - (0, _jquery2.default)(this._el).toggleClass(CLASS_SINGLE_CONTENT, !activate); - } - - /** - * toggle split - */ - - }, { - key: 'toggleSplitView', - value: function toggleSplitView() { - (0, _jquery2.default)(this._el).toggleClass(CLASS_SINGLE_CONTENT); - } - - /** - * is scroll synced - * @returns {boolean} - true for synced, false for each scroll - */ - - }, { - key: 'isScrollSynced', - value: function isScrollSynced() { - return (0, _jquery2.default)(this._el).hasClass(CLASS_SCROLL_SYNC); - } - - /** - * is split view - * @returns {boolean} - true for split view, false for single view - */ - - }, { - key: 'isSplitView', - value: function isSplitView() { - return !(0, _jquery2.default)(this._el).hasClass(CLASS_SINGLE_CONTENT); - } - - /** - * sync scroll - */ - - }, { - key: 'sync', - value: function sync() { - if (!this._contentElements.left || !this._contentElements.right) { - return; - } - - var wrapperHeight = this._contentWrapper.clientHeight; - var scrollTop = this._contentWrapper.scrollTop; - - var leftElement = this._contentElements.left; - var rightElement = this._contentElements.right; - - var scrollingElement = leftElement.offsetHeight - wrapperHeight > 0 ? leftElement : rightElement; - var followingElement = scrollingElement === leftElement ? rightElement : leftElement; - - var scrollingElementHeight = scrollingElement.offsetHeight; - var scrollingElementScrollMax = Math.max(scrollingElementHeight - wrapperHeight, 0); - var followingElementHeight = Math.max(followingElement.offsetHeight, wrapperHeight); - var followingElementTopMax = scrollingElementHeight - followingElementHeight; - - scrollingElement.style.top = '0px'; - followingElement.style.top = scrollTop / scrollingElementScrollMax * followingElementTopMax + 'px'; - } - - /** - * scroll top - * @param {number} top - scroll top in pixel - */ - - }, { - key: 'scrollTop', - value: function scrollTop(top) { - this._contentWrapper.scrollTop = top; - } - }]); - - return ScrollSyncSplit; -}(); - -exports.default = ScrollSyncSplit; - -/***/ }), -/* 110 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _codeMirrorExt = __webpack_require__(32); - -var _codeMirrorExt2 = _interopRequireDefault(_codeMirrorExt); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements code block editor - * @author NHN FE Development Lab - */ - - -var EVENT_LANGUAGE_CHANGED = 'language-changed'; - -/** - * Class Code Block Editor - * @param {HTMLElement} el - code block editor container element - * @param {EventManager} eventManager - event manager - * @ignore - */ - -var CodeBlockEditor = function (_CodeMirrorExt) { - _inherits(CodeBlockEditor, _CodeMirrorExt); - - function CodeBlockEditor(el, eventManager) { - _classCallCheck(this, CodeBlockEditor); - - var _this = _possibleConstructorReturn(this, (CodeBlockEditor.__proto__ || Object.getPrototypeOf(CodeBlockEditor)).call(this, el, { - singleCursorHeightPerLine: false, - theme: 'none' - })); - - _this._language = ''; - _this._eventManager = eventManager; - - _this._initEvent(); - return _this; - } - - _createClass(CodeBlockEditor, [{ - key: '_initEvent', - value: function _initEvent() { - var _this2 = this; - - this.on('cursorActivity', this._onRequireScrollIntoView.bind(this)); - this.on('beforeChange', function (cm, ev) { - if (ev.origin === 'paste') { - _this2._eventManager.emit('pasteBefore', { - source: 'codeblock', - data: ev - }); - } - }); - } - }, { - key: '_onRequireScrollIntoView', - value: function _onRequireScrollIntoView() { - var cursor = this.getCursor(); - var wrapper = this.getWrapperElement(); - - // CodeMirror cursorActivity event fires before actually attach a new line element to DOM - // we should proceed at next tick - setTimeout(function () { - var lineElement = wrapper.querySelector('pre:nth-child(' + (cursor.line + 1) + ')'); - (0, _jquery2.default)(lineElement).trigger('requireScrollIntoView'); - }, 0); - } - - /** - * load code from code block element - * @param {HTMLElement} codeBlockElement - code block element - */ - - }, { - key: 'load', - value: function load(codeBlockElement) { - var el = codeBlockElement.cloneNode(true); - this.setLanguage(el.getAttribute('data-language') || ''); - this.setEditorCodeText(el.textContent); - } - - /** - * save code to code block element - * @param {HTMLElement} codeBlockElement - code block element - */ - - }, { - key: 'save', - value: function save(codeBlockElement) { - codeBlockElement.innerHTML = ''; - codeBlockElement.textContent = this.getEditorCodeText(); - codeBlockElement.setAttribute('data-language', this._language); - (0, _jquery2.default)(codeBlockElement).trigger(EVENT_LANGUAGE_CHANGED); - } - - /** - * clear code and language - */ - - }, { - key: 'clear', - value: function clear() { - this.setLanguage(''); - this.setEditorCodeText(''); - } - - /** - * get code language - * @returns {string} - code language - */ - - }, { - key: 'getLanguage', - value: function getLanguage() { - return this._language; - } - - /** - * set code language - * @param {string} [language=''] - code language - */ - - }, { - key: 'setLanguage', - value: function setLanguage() { - var language = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; - - this._language = language; - } - - /** - * get code text - * @returns {string} - code text - */ - - }, { - key: 'getEditorCodeText', - value: function getEditorCodeText() { - return this.getValue(); - } - - /** - * set code text - * @param {string} [code=''] - code text - */ - - }, { - key: 'setEditorCodeText', - value: function setEditorCodeText() { - var code = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; - - this.setValue(code); - } - - /** - * refresh. call if codemirror resized - */ - - }, { - key: 'refresh', - value: function refresh() { - this.cm.refresh(); - } - }]); - - return CodeBlockEditor; -}(_codeMirrorExt2.default); - -exports.default = CodeBlockEditor; - -/***/ }), -/* 111 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _preview = __webpack_require__(35); - -var _preview2 = _interopRequireDefault(_preview); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @fileoverview Implements CodeBlockPreview - * @author NHN FE Development Lab - */ - - -var EVENT_REQUIRE_SCROLL_SYNC = 'requireScrollSync'; - -/** - * Class Code block preview - * @param {jQuery} $el - base element - * @param {EventManager} eventManager - event manager - * @param {Convertor} convertor - convertor - * @param {CodeBlockEditor} codeBlockEditor - code block editor - * @ignore - */ - -var CodeBlockPreview = function (_Preview) { - _inherits(CodeBlockPreview, _Preview); - - function CodeBlockPreview($el, eventManager, convertor, codeBlockEditor) { - _classCallCheck(this, CodeBlockPreview); - - var _this = _possibleConstructorReturn(this, (CodeBlockPreview.__proto__ || Object.getPrototypeOf(CodeBlockPreview)).call(this, $el, eventManager, convertor, true)); - - _this._codeBlockEditor = codeBlockEditor; - - _this._initEvent(); - return _this; - } - - _createClass(CodeBlockPreview, [{ - key: '_initEvent', - value: function _initEvent() { - var _this2 = this; - - this._codeBlockEditor.on('update', function () { - return _this2.lazyRunner.run('refresh'); - }); - } - - /** - * refresh preview - * @override - */ - - }, { - key: 'refresh', - value: function refresh() { - var language = this._codeBlockEditor.getLanguage(); - var codeText = this._codeBlockEditor.getEditorCodeText(); - - _get(CodeBlockPreview.prototype.__proto__ || Object.getPrototypeOf(CodeBlockPreview.prototype), 'refresh', this).call(this, '```' + language + '\n' + codeText + '\n```'); - this.$el.trigger(EVENT_REQUIRE_SCROLL_SYNC); - } - - /** - * clear preview - */ - - }, { - key: 'clear', - value: function clear() { - _get(CodeBlockPreview.prototype.__proto__ || Object.getPrototypeOf(CodeBlockPreview.prototype), 'render', this).call(this, ''); - } - }]); - - return CodeBlockPreview; -}(_preview2.default); - -exports.default = CodeBlockPreview; - -/***/ }), -/* 112 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * @fileoverview Implements UI code block languages combo - * @author NHN FE Development Lab - */ - - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -var _keyMapper = __webpack_require__(22); - -var _keyMapper2 = _interopRequireDefault(_keyMapper); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Class CodeBlockLanguagesCombo - * @param {EventManager} eventManager - event manager instance - * @ignore - */ -var CodeBlockLanguagesCombo = function () { - function CodeBlockLanguagesCombo(eventManager) { - _classCallCheck(this, CodeBlockLanguagesCombo); - - this._eventManager = eventManager; - - this._initDOM(); - this._initDOMEvent(); - } - - _createClass(CodeBlockLanguagesCombo, [{ - key: '_initDOM', - value: function _initDOM() { - this._inputLanguage = (0, _jquery2.default)('').get(0); - this._wrapper = (0, _jquery2.default)('').get(0); - this._wrapper.appendChild(this._inputLanguage); - } - }, { - key: '_initDOMEvent', - value: function _initDOMEvent() { - var _this = this; - - this._inputLanguage.addEventListener('keydown', function (event) { - return _this._onKeyEvent(event); - }); - this._inputLanguage.addEventListener('focus', function () { - return _this._showPopupCodeBlockLanguages(); - }); - this._inputLanguage.addEventListener('focusout', function () { - return _this._onFocusOut(); - }); - this._wrapper.addEventListener('mousedown', function (ev) { - if (ev.target !== _this._wrapper) { - return; - } - ev.preventDefault(); - _this._toggleFocus(); - }); - } - - /** - * show popup - * @private - */ - - }, { - key: '_showPopupCodeBlockLanguages', - value: function _showPopupCodeBlockLanguages() { - var _this2 = this; - - var clientRect = this._inputLanguage.getBoundingClientRect(); - (0, _jquery2.default)(this._wrapper).toggleClass('active', true); - this.active = true; - - this._popupCodeBlockLanguages = this._eventManager.emitReduce('openPopupCodeBlockLanguages', { - language: this._prevStoredLanguage, - offset: { - left: clientRect.left, - top: clientRect.bottom - }, - callback: { - selected: function selected(selectedLanguage) { - return _this2._onLanguageSelectedFromList(selectedLanguage); - }, - dismissed: function dismissed() { - _this2._popupCodeBlockLanguages = null; - } - } - }); - } - }, { - key: '_toggleFocus', - value: function _toggleFocus() { - var inputLanguage = this._inputLanguage; - if ((0, _jquery2.default)(this._wrapper).hasClass('active')) { - inputLanguage.blur(); - } else { - inputLanguage.focus(); - } - } - }, { - key: '_onFocusOut', - value: function _onFocusOut() { - (0, _jquery2.default)(this._wrapper).toggleClass('active', false); - this._inputLanguage.value = this._prevStoredLanguage; - this._hidePopupCodeBlockLanguages(); - } - }, { - key: '_onKeyEvent', - value: function _onKeyEvent(event) { - if (this._popupCodeBlockLanguages) { - switch (event.which) { - case _keyMapper2.default.keyCode('UP'): - this._popupCodeBlockLanguages.prev(); - event.preventDefault(); - break; - case _keyMapper2.default.keyCode('DOWN'): - this._popupCodeBlockLanguages.next(); - event.preventDefault(); - break; - case _keyMapper2.default.keyCode('ENTER'): - case _keyMapper2.default.keyCode('TAB'): - { - var language = this._popupCodeBlockLanguages.getCurrentLanguage(); - this._inputLanguage.value = language; - this._storeInputLanguage(); - event.preventDefault(); - break; - } - default: - this._popupCodeBlockLanguages.hide(); - } - } else if (event.which === _keyMapper2.default.keyCode('ENTER') || event.which === _keyMapper2.default.keyCode('TAB')) { - this._storeInputLanguage(); - event.preventDefault(); - } - } - }, { - key: '_onLanguageSelectedFromList', - value: function _onLanguageSelectedFromList(selectedLanguage) { - this._inputLanguage.value = selectedLanguage; - this._storeInputLanguage(); - } - - /** - * set a callback to be called on language selected - * @param {function} callback - callback function - * @protected - */ - - }, { - key: 'setOnLanguageSelected', - value: function setOnLanguageSelected(callback) { - this._onLanguageSelected = callback; - } - - /** - * hide popup - * @private - */ - - }, { - key: '_hidePopupCodeBlockLanguages', - value: function _hidePopupCodeBlockLanguages() { - this._eventManager.emit('closePopupCodeBlockLanguages'); - } - - /** - * set language - * @param {string} language - code block language - * @protected - */ - - }, { - key: 'setLanguage', - value: function setLanguage(language) { - this._prevStoredLanguage = language; - this._inputLanguage.value = language; - } - - /** - * store selection(typed) language & hide popup - * @private - */ - - }, { - key: '_storeInputLanguage', - value: function _storeInputLanguage() { - var selectedLanguage = this._inputLanguage.value; - - this.setLanguage(selectedLanguage); - if (this._onLanguageSelected) { - this._onLanguageSelected(selectedLanguage); - } - - this._hidePopupCodeBlockLanguages(); - } - - /** - * get element body - * @returns {HTMLElement} - CodeBlockLanguagesCombo body element - * @protected - */ - - }, { - key: 'getElement', - value: function getElement() { - return this._wrapper; - } - }]); - - return CodeBlockLanguagesCombo; -}(); - -exports.default = CodeBlockLanguagesCombo; - -/***/ }), -/* 113 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _toMark = __webpack_require__(24); - -var _toMark2 = _interopRequireDefault(_toMark); - -var _domUtils = __webpack_require__(4); - -var _domUtils2 = _interopRequireDefault(_domUtils); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Check if given node is valid delimiter run. - * According to common-mark spec, following examples are not valid delimiter runs. - * 1. opening (*|**) preceded by an alphanumeric and followed by a punctuation. - * (ex: a**~~c~~b**) - * 2. closing (*|**) preceded by a punctuation and followed by an alphanumeric. - * (ex: **b~~c~~**a) - * @see {@link https://spec.commonmark.org/0.29/#delimiter-run} - * @see {@link https://github.com/commonmark/commonmark-spec/issues/611#issuecomment-533578503} - */ -function isValidDelimiterRun(node) { - var isElemNode = _domUtils2.default.isElemNode, - isTextNode = _domUtils2.default.isTextNode; - - var isInvalidOpener = isTextNode(node.previousSibling) && isElemNode(node.firstChild); - var isInvalidCloser = isTextNode(node.nextSibling) && isElemNode(node.lastChild); - - return !isInvalidOpener && !isInvalidCloser; -} - -function convertEmphasis(node, subContent, delimiter) { - var FIND_BEFORE_AND_AFTER_SPACES_RX = /^(\s*)((?:.|\n)*\S)(\s*)$/m; - - var _subContent$match = subContent.match(FIND_BEFORE_AND_AFTER_SPACES_RX), - beforeSpaces = _subContent$match[1], - trimmedContent = _subContent$match[2], - afterSpaces = _subContent$match[3]; - - var convertedContent = void 0; - - if (isValidDelimiterRun(node)) { - convertedContent = '' + delimiter + trimmedContent + delimiter; - } else { - var tagName = node.nodeName.toLowerCase(); - - convertedContent = '<' + tagName + '>' + trimmedContent + ''; - } - - return '' + beforeSpaces + convertedContent + afterSpaces; -} - -exports.default = _toMark2.default.Renderer.factory(_toMark2.default.gfmRenderer, { - 'EM, I': function EMI(node, subContent) { - if (this.isEmptyText(subContent)) { - return ''; - } - - return convertEmphasis(node, subContent, '*'); - }, - 'STRONG, B': function STRONGB(node, subContent) { - if (this.isEmptyText(subContent)) { - return ''; - } - - return convertEmphasis(node, subContent, '**'); - }, - 'DEL, S': function DELS(node, subContent) { - if (this.isEmptyText(subContent)) { - return ''; - } - - return convertEmphasis(node, subContent, '~~'); - } -}); - -/***/ }), -/* 114 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _emphasisCommon = __webpack_require__(26); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** -* @fileoverview Implements Bold markdown command -* @author NHN FE Development Lab -*/ -var boldRangeRegex = /^(\*{2}|_{2}).*\1$/; -var boldContentRegex = /[*_]{2,}([^*_]*)[*_]{2,}/g; -var boldSymbol = '**'; - -/** - * Bold - * Add bold markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/Bold - * @ignore - */ -var Bold = _commandManager2.default.command('markdown', /** @lends Bold */{ - name: 'Bold', - keyMap: ['CTRL+B', 'META+B'], - /** - * Command Handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - var originRange = mde.getRange(); - - (0, _emphasisCommon.changeSyntax)(doc, originRange, boldSymbol, boldRangeRegex, boldContentRegex); - - cm.focus(); - } -}); - -exports.default = Bold; - -/***/ }), -/* 115 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _emphasisCommon = __webpack_require__(26); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview Implements Italic markdown command - * @author NHN FE Development Lab - */ -var boldItalicRangeRegex = /^(\*{3}|_{3}).*\1$/; -var boldRangeRegex = /^(\*{2}|_{2}).*\1$/; -var italicRangeRegex = /^(\*|_).*\1$/; -var italicContentRegex = /([^*_])[*_]([^*_]+)[*_]([^*_])/g; - -var isBoldItalic = function isBoldItalic(t) { - return boldItalicRangeRegex.test(t); -}; -var isBold = function isBold(t) { - return boldRangeRegex.test(t); -}; -var isItalic = function isItalic(t) { - return italicRangeRegex.test(t); -}; - -var italicSymbol = '*'; -var boldSymbol = '**'; -var boldItalicSymbol = '***'; -var italicLength = italicSymbol.length; -var boldLength = boldSymbol.length; -var boldItalicLength = boldItalicSymbol.length; - -/** - * remove italic syntax in the middle of given text - * @param {string} text - text selected - * @returns {string} - text eliminated all italic in the middle of it's content - * @ignore - */ -var removeItalicInsideText = function removeItalicInsideText(text) { - return text ? text.replace(italicContentRegex, '$1$2$3') : ''; -}; - -var replaceText = function replaceText(doc, text, range) { - // Check 3 cases when both text and expand text - // case 1 : bold & italic (when expand 3 both front and end) => remove italic - // case 2 : bold (when expand 2 both front and end) => append - // case 3 : italic (expand 1 both front and end) => remove - var expandReplaceBind = _emphasisCommon.expandReplace.bind(this, doc, range); - - return expandReplaceBind(boldItalicLength, isBoldItalic, function (t) { - return (0, _emphasisCommon.removeSyntax)(t, italicSymbol); - }) || expandReplaceBind(boldLength, isBold, function (t) { - return (0, _emphasisCommon.appendSyntax)(removeItalicInsideText(t), italicSymbol); - }) || expandReplaceBind(italicLength, isItalic, function (t) { - return (0, _emphasisCommon.removeSyntax)(t, italicSymbol); - }) || (0, _emphasisCommon.replace)(doc, text, isBoldItalic, function (t) { - return (0, _emphasisCommon.removeSyntax)(t, italicSymbol); - }) || (0, _emphasisCommon.replace)(doc, text, isBold, function (t) { - return (0, _emphasisCommon.appendSyntax)(removeItalicInsideText(t), italicSymbol); - }) || (0, _emphasisCommon.replace)(doc, text, isItalic, function (t) { - return (0, _emphasisCommon.removeSyntax)(t, italicSymbol); - }); -}; - -var replaceEmptyText = function replaceEmptyText(doc, range) { - // Check 3 cases when expand text - // case 1 : bold & italic => remove italic - // case 2 : bold => append - // case 3 : italic => remove - // if there is no match, make italic - return (0, _emphasisCommon.expandReplace)(doc, range, boldItalicLength, isBoldItalic, function (t) { - return (0, _emphasisCommon.removeSyntax)(t, italicSymbol); - }) || (0, _emphasisCommon.expandReplace)(doc, range, boldLength, isBold, function (t) { - return (0, _emphasisCommon.appendSyntax)(t, italicSymbol); - }) || (0, _emphasisCommon.expandReplace)(doc, range, italicLength, isItalic, function () { - return ''; - }) || doc.replaceSelection('' + italicSymbol + italicSymbol, 'around'); -}; - -/** - * Italic - * Add italic markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/Italic - * @ignore - */ -var Italic = _commandManager2.default.command('markdown', /** @lends Italic */{ - name: 'Italic', - keyMap: ['CTRL+I', 'META+I'], - /** - * Command handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - - var _doc$getCursor = doc.getCursor(), - line = _doc$getCursor.line, - ch = _doc$getCursor.ch; - - var range = mde.getRange(); - var selectionStr = doc.getSelection(); - - if (selectionStr) { - // check selectionStr match bold & italic, bold, italic and then - // if there is no match, append italic - if (!replaceText(doc, selectionStr, range)) { - // Before append italic, remove italic inside text and then append italic - // Example: One*Two*Three => *OneTwoThree* - doc.replaceSelection((0, _emphasisCommon.appendSyntax)(removeItalicInsideText(selectionStr), italicSymbol), 'around'); - } - } else { - replaceEmptyText(doc, range); - - var afterSelectStr = doc.getSelection(); - var size = ch; - - // If text was not selected, after replace text, move cursor - if (isBoldItalic(afterSelectStr) || isItalic(afterSelectStr) && !isBold(afterSelectStr)) { - // For example **|** => ***|*** (move cusor +symbolLenth) - size += italicLength; - } else { - // For example *|* => | (move cusor -symbolLenth) - size -= italicLength; - } - - doc.setCursor(line, size); - } - - cm.focus(); - } -}); - -exports.default = Italic; - -/***/ }), -/* 116 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _emphasisCommon = __webpack_require__(26); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview Implements StrikeThrough markdown command - * @author NHN FE Development Lab - */ -var strikeRangeRegex = /^~~.*~~$/; -var strikeContentRegex = /~~([^~]*)~~/g; -var strikeSymbol = '~~'; - -/** - * Strike - * Add strike markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/Strike - * @ignore - */ -var Strike = _commandManager2.default.command('markdown', /** @lends Strike */{ - name: 'Strike', - keyMap: ['CTRL+S', 'META+S'], - /** - * Command handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - var originRange = mde.getRange(); - - (0, _emphasisCommon.changeSyntax)(doc, originRange, strikeSymbol, strikeRangeRegex, strikeContentRegex); - - cm.focus(); - } -}); - -exports.default = Strike; - -/***/ }), -/* 117 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var BlockquoteRegex = /^> ?/; - -/** - * Blockquote - * Add blockquote markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/Blockquote - * @ignore - */ -/** -* @fileoverview Implements Blockquote markdown command -* @author NHN FE Development Lab -*/ -var Blockquote = _commandManager2.default.command('markdown', /** @lends Blockquote */{ - name: 'Blockquote', - keyMap: ['ALT+Q', 'ALT+Q'], - /** - * command handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - - var range = mde.getCurrentRange(); - - var from = { - line: range.from.line, - ch: 0 - }; - - var to = { - line: range.to.line, - ch: doc.getLineHandle(range.to.line).text.length - }; - - var textToModify = doc.getRange(from, to); - var textLinesToModify = textToModify.split('\n'); - var isNeedToRemove = this._haveBlockquote(textLinesToModify); - var resultText = void 0; - - if (isNeedToRemove) { - resultText = this._removeBlockquote(textLinesToModify); - } else { - resultText = this._addBlockquote(textLinesToModify); - } - - doc.replaceRange(resultText.join('\n'), from, to); - - if (isNeedToRemove) { - var length = textLinesToModify.length; - if (this._isBlockquoteWithSpace(textLinesToModify[length - 1])) { - range.to.ch -= 2; - } else { - range.to.ch -= 1; - } - } else { - range.to.ch += 2; - } - - doc.setCursor(range.to); - - cm.focus(); - }, - - - /** - * check all text in textArr starts with '>' - * @param {Array} textArr - text array - * @returns {boolean} - true if all text in textArr starts with '>' - * @private - */ - _haveBlockquote: function _haveBlockquote(textArr) { - for (var i = 0; i < textArr.length; i += 1) { - if (!BlockquoteRegex.test(textArr[i])) { - return false; - } - } - - return true; - }, - - - /** - * add '> ' to all text in textArr - * @param {Array} textArr - text array - * @returns {Array} - new text array added '> ' - * @private - */ - _addBlockquote: function _addBlockquote(textArr) { - return textArr.map(function (text) { - return '> ' + text; - }); - }, - - - /** - * remove '> ' or '>' to all text in textArr - * @param {Array} textArr - text array - * @returns {Array} - new text array removed '> ' or '>' - * @private - */ - _removeBlockquote: function _removeBlockquote(textArr) { - return textArr.map(function (text) { - return text.replace(BlockquoteRegex, ''); - }); - }, - - - /** - * check text start '> ' - * @param {string} text - text - * @returns {boolean} - if text start '> ', true - * @private - */ - _isBlockquoteWithSpace: function _isBlockquoteWithSpace(text) { - return (/^> /.test(text) - ); - } -}); - -exports.default = Blockquote; - -/***/ }), -/* 118 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview Implements Heading markdown command - * @author NHN FE Development Lab - */ -var FIND_HEADING_RX = /^#+\s/g; - -/** - * Heading - * Add heading markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/Heading - * @ignore - */ -var Heading = _commandManager2.default.command('markdown', /** @lends Heading */{ - name: 'Heading', - /** - * Command Handler - * @param {MarkdownEditor} mde MarkdownEditor instance - * @param {number} size heading size - */ - exec: function exec(mde, size) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - - var range = mde.getCurrentRange(); - - var from = { - line: range.from.line, - ch: 0 - }; - - var to = { - line: range.to.line, - ch: doc.getLineHandle(range.to.line).text.length - }; - - var lengthOfCurrentLineBefore = doc.getLine(to.line).length; - var textToModify = doc.getRange(from, to); - var textLinesToModify = textToModify.split('\n'); - - _tuiCodeSnippet2.default.forEachArray(textLinesToModify, function (line, index) { - textLinesToModify[index] = getHeadingMarkdown(line, size); - }); - - doc.replaceRange(textLinesToModify.join('\n'), from, to); - - range.to.ch += doc.getLine(to.line).length - lengthOfCurrentLineBefore; - - doc.setSelection(from, range.to); - - cm.focus(); - } -}); - -/** - * Get heading markdown - * @param {string} text Source test - * @param {number} size size - * @returns {string} - */ -function getHeadingMarkdown(text, size) { - var foundedHeading = text.match(FIND_HEADING_RX); - var heading = ''; - - do { - heading += '#'; - size -= 1; - } while (size > 0); - - if (foundedHeading) { - var _text$split = text.split(foundedHeading[0]); - - text = _text$split[1]; - } - - return heading + ' ' + text; -} - -exports.default = Heading; - -/***/ }), -/* 119 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Paragraph - * Convert selected lines to paragraph - * @extends Command - * @module markdownCommands/Paragraph - * @ignore - */ -/** - * @fileoverview Implements Paragraph markdown command - * @author NHN FE Development Lab - */ -var Paragraph = _commandManager2.default.command('markdown', /** @lends Paragraph */{ - name: 'Paragraph', - /** - * Command Handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - var range = mde.getCurrentRange(); - var from = { - line: range.from.line, - ch: 0 - }; - var to = { - line: range.to.line, - ch: doc.getLineHandle(range.to.line).text.length - }; - - var lengthOfCurrentLineBefore = doc.getLine(to.line).length; - var textToModify = doc.getRange(from, to); - var textLines = textToModify.split('\n'); - - _tuiCodeSnippet2.default.forEachArray(textLines, function (line, index) { - textLines[index] = getParagraphMarkdown(line); - }); - - doc.replaceRange(textLines.join('\n'), from, to); - - range.to.ch += doc.getLine(to.line).length - lengthOfCurrentLineBefore; - - doc.setSelection(from, to); - - cm.focus(); - } -}); -/** - * Get paragraph markdown lineText - * @param {string} lineText line lineText - * @returns {string} - */ -function getParagraphMarkdown(lineText) { - var headingRx = /^(#{1,6}| *((?:\*|-|\d\.)(?: \[[ xX]])?)) /; - - return lineText.replace(headingRx, ''); -} - -exports.default = Paragraph; - -/***/ }), -/* 120 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * HR - * Add HR markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/HR - * @ignore - */ -var HR = _commandManager2.default.command('markdown', /** @lends HR */{ - name: 'HR', - keyMap: ['CTRL+L', 'META+L'], - /** - * Command handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - var replaceText = ''; - - var range = mde.getCurrentRange(); - - var from = { - line: range.from.line, - ch: range.from.ch - }; - - var to = { - line: range.to.line, - ch: range.to.ch - }; - - if (range.collapsed) { - replaceText = doc.getLine(from.line); - from.ch = 0; - to.ch = doc.getLineHandle(range.to.line).text.length; - } - - if (doc.getLine(from.line).length) { - replaceText += '\n\n* * *\n\n'; - } else { - replaceText += '\n* * *\n'; - } - - doc.replaceRange(replaceText, from, to); - - cm.focus(); - } -}); /** - * @fileoverview Implements HR markdown command - * @author NHN FE Development Lab - */ - -exports.default = HR; - -/***/ }), -/* 121 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _importManager = __webpack_require__(15); - -var _importManager2 = _interopRequireDefault(_importManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** -* @fileoverview Implements Addlink markdown command -* @author NHN FE Development Lab -*/ -var decodeURIGraceful = _importManager2.default.decodeURIGraceful, - encodeMarkdownCharacters = _importManager2.default.encodeMarkdownCharacters, - escapeMarkdownCharacters = _importManager2.default.escapeMarkdownCharacters; - -/** - * AddLink - * Add link markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/AddLink - * @ignore - */ - -var AddLink = _commandManager2.default.command('markdown', /** @lends AddLink */{ - name: 'AddLink', - /** - * command handler for AddLink - * @param {MarkdownEditor} mde - MarkdownEditor instance - * @param {object} data - data for image - */ - exec: function exec(mde, data) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - - var range = mde.getCurrentRange(); - - var from = { - line: range.from.line, - ch: range.from.ch - }; - - var to = { - line: range.to.line, - ch: range.to.ch - }; - - var linkText = data.linkText, - url = data.url; - - linkText = decodeURIGraceful(linkText); - linkText = escapeMarkdownCharacters(linkText); - url = encodeMarkdownCharacters(url); - - var replaceText = '[' + linkText + '](' + url + ')'; - - doc.replaceRange(replaceText, from, to); - - cm.focus(); - } -}); - -exports.default = AddLink; - -/***/ }), -/* 122 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _importManager = __webpack_require__(15); - -var _importManager2 = _interopRequireDefault(_importManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** -* @fileoverview Implments AddImage markdown command -* @author NHN FE Development Lab -*/ -var decodeURIGraceful = _importManager2.default.decodeURIGraceful, - encodeMarkdownCharacters = _importManager2.default.encodeMarkdownCharacters, - escapeMarkdownCharacters = _importManager2.default.escapeMarkdownCharacters; - -/** - * AddImage - * Add Image markdown syntax to markdown Editor - * @extends Command - * @module markdownCommands/AddImage - * @ignore - */ - -var AddImage = _commandManager2.default.command('markdown', /** @lends AddImage */{ - name: 'AddImage', - /** - * Command Handler - * @param {MarkdownEditor} mde MarkdownEditor instance - * @param {object} data data for image - */ - exec: function exec(mde, data) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - - var range = mde.getCurrentRange(); - - var from = { - line: range.from.line, - ch: range.from.ch - }; - - var to = { - line: range.to.line, - ch: range.to.ch - }; - - var altText = data.altText, - imageUrl = data.imageUrl; - - altText = decodeURIGraceful(altText); - altText = escapeMarkdownCharacters(altText); - imageUrl = encodeMarkdownCharacters(imageUrl); - var replaceText = '![' + altText + '](' + imageUrl + ')'; - - doc.replaceRange(replaceText, from, to, '+addImage'); - - cm.focus(); - } -}); - -exports.default = AddImage; - -/***/ }), -/* 123 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * UL - * Add unordered list markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/UL - * @ignore - */ -var UL = _commandManager2.default.command('markdown', /** @lends UL */{ - name: 'UL', - keyMap: ['CTRL+U', 'META+U'], - /** - * Command handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var range = mde.getCurrentRange(); - var listManager = mde.componentManager.getManager('list'); - - listManager.changeSyntax(range, 'ul'); - } -}); /** - * @fileoverview Implements UL markdown command - * @author NHN FE Development Lab - */ -exports.default = UL; - -/***/ }), -/* 124 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * OL - * Add ordered list markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/OL - * @ignore - */ -var OL = _commandManager2.default.command('markdown', /** @lends OL */{ - name: 'OL', - keyMap: ['CTRL+O', 'META+O'], - /** - * Command handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var range = mde.getCurrentRange(); - var listManager = mde.componentManager.getManager('list'); - - listManager.changeSyntax(range, 'ol'); - } -}); /** - * @fileoverview Implements OL markdown command - * @author NHN FE Development Lab - */ - -exports.default = OL; - -/***/ }), -/* 125 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Indent - * Add Indent markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/inent - * @ignore - */ -var Indent = _commandManager2.default.command('markdown', /** @lends Indent */{ - name: 'Indent', - /** - * Command handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var cm = mde.getEditor(); - cm.execCommand('indentOrderedList'); - } -}); /** - * @fileoverview Implements Indent markdown command - * @author NHN FE Development Lab - */ - -exports.default = Indent; - -/***/ }), -/* 126 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Outdent - * Add Outdent markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/outdent - * @ignore - */ -var Outdent = _commandManager2.default.command('markdown', /** @lends Outdent */{ - name: 'Outdent', - /** - * Command handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var cm = mde.getEditor(); - cm.execCommand('indentLessOrderedList'); - } -}); /** - * @fileoverview Implements Outdent markdown command - * @author NHN FE Development Lab - */ - -exports.default = Outdent; - -/***/ }), -/* 127 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Table - * Add table markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/Table - * @ignore - */ -var Table = _commandManager2.default.command('markdown', /** @lends Table */{ - name: 'Table', - /** - * Command handler - * @param {MarkdownEditor} mde MarkdownEditor instance - * @param {number} col column count - * @param {number} row row count - * @param {Array} data initial table data - */ - exec: function exec(mde, col, row, data) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - var table = '\n'; - - if (cm.getCursor().ch > 0) { - table += '\n'; - } - - table += makeHeader(col, data); - table += makeBody(col, row - 1, data); - - doc.replaceSelection(table); - - if (!data) { - cm.setCursor(cm.getCursor().line - row, 2); - } - - mde.focus(); - } -}); - -/** - * makeHeader - * make table header markdown string - * @param {number} col Column count - * @param {array} data Cell's text content - * @returns {string} markdown string - */ -/** - * @fileoverview Implements Table markdown command - * @author NHN FE Development Lab - */ - -function makeHeader(col, data) { - var header = '|'; - var border = '|'; - var index = 0; - - while (col) { - if (data) { - header += ' ' + data[index] + ' |'; - index += 1; - } else { - header += ' |'; - } - - border += ' --- |'; - - col -= 1; - } - - return header + '\n' + border + '\n'; -} - -/** - * makeBody - * make table body markdown string - * @param {number} col column count - * @param {number} row row count - * @param {Array} data initial table data - * @returns {string} html string - */ -function makeBody(col, row, data) { - var body = ''; - var index = col; - - for (var irow = 0; irow < row; irow += 1) { - body += '|'; - - for (var icol = 0; icol < col; icol += 1) { - if (data) { - body += ' ' + data[index] + ' |'; - index += 1; - } else { - body += ' |'; - } - } - - body += '\n'; - } - - body = body.replace(/\n$/g, ''); - - return body; -} -exports.default = Table; - -/***/ }), -/* 128 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Task - * @extends Command - * @module markdownCommands/Task - * @ignore - */ -var Task = _commandManager2.default.command('markdown', /** @lends Task */{ - name: 'Task', - keyMap: ['ALT+T', 'ALT+T'], - /** - * Command handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var range = mde.getCurrentRange(); - var listManager = mde.componentManager.getManager('list'); - - listManager.changeSyntax(range, 'task'); - } -}); /** - * @fileoverview Implements Task markdown command - * @author NHN FE Development Lab - */ -exports.default = Task; - -/***/ }), -/* 129 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var codeRangeRegex = /^`([^`]+)`$/; /** - * @fileoverview Implements Code markdown command - * @author NHN FE Development Lab - */ - -var codeContentRegex = /`([^`]+)`/g; - -/** - * Code - * Add code markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/Code - * @ignore - */ -var Code = _commandManager2.default.command('markdown', /** @lends Code */{ - name: 'Code', - keyMap: ['SHIFT+CTRL+C', 'SHIFT+META+C'], - /** - * Command Handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - var selection = doc.getSelection(); - var cursor = cm.getCursor(); - var hasSyntax = this.hasStrikeSyntax(selection); - - var result = void 0; - if (hasSyntax) { - result = this.remove(selection); - result = this._removeCodeSyntax(result); - } else { - result = this._removeCodeSyntax(selection); - result = this.append(result); - } - - doc.replaceSelection(result, 'around'); - - if (!selection && !hasSyntax) { - this.setCursorToCenter(doc, cursor, hasSyntax); - } - - cm.focus(); - }, - - - /** - * set cursor to center - * @param {CodeMirror.doc} doc - codemirror document - * @param {object} cursor - codemirror cursor - * @param {boolean} isRemoved - whether it involes deletion - */ - setCursorToCenter: function setCursorToCenter(doc, cursor, isRemoved) { - var pos = isRemoved ? -1 : 1; - doc.setCursor(cursor.line, cursor.ch + pos); - }, - - - /** - * has code syntax - * @param {string} text Source text - * @returns {boolean} true if the given text has a code syntax - */ - hasStrikeSyntax: function hasStrikeSyntax(text) { - return codeRangeRegex.test(text); - }, - - - /** - * apply Code - * @param {string} text - selected text - * @returns {string} - text after code syntax applied - */ - append: function append(text) { - return '`' + text + '`'; - }, - - - /** - * remove Code - * @param {string} text - selected text - * @returns {string} - text after code syntax removed - */ - remove: function remove(text) { - return text.substr(1, text.length - 2); - }, - - - /** - * remove bold syntax in the middle of given text - * @param {string} text - text selected - * @returns {string} - text eliminated all code in the middle of it's content - * @private - */ - _removeCodeSyntax: function _removeCodeSyntax(text) { - return text ? text.replace(codeContentRegex, '$1') : ''; - } -}); - -exports.default = Code; - -/***/ }), -/* 130 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * CodeBlock - * Add CodeBlock markdown syntax to markdown editor - * @extends Command - * @module markdownCommands/CodeBlock - * @ignore - */ -var CodeBlock = _commandManager2.default.command('markdown', /** @lends CodeBlock */{ - name: 'CodeBlock', - keyMap: ['SHIFT+CTRL+P', 'SHIFT+META+P'], - /** - * Command handler - * @param {MarkdownEditor} mde MarkdownEditor instance - */ - exec: function exec(mde) { - var cm = mde.getEditor(); - var doc = cm.getDoc(); - var range = mde.getCurrentRange(); - var replaceText = ['```', doc.getSelection(), '```']; - var cursorOffset = 1; - // insert a line break to the front if the selection starts in the middle of a text - if (range.from.ch !== 0) { - replaceText.unshift(''); - cursorOffset += 1; - } - // insert a line break to the end if the selection has trailing text - if (range.to.ch !== doc.getLine(range.to.line).length) { - replaceText.push(''); - } - doc.replaceSelection(replaceText.join('\n')); - - cm.setCursor(range.from.line + cursorOffset, 0); - - cm.focus(); - } -}); /** - * @fileoverview Implements CodeBlock markdown command - * @author NHN FE Development Lab - */ -exports.default = CodeBlock; - -/***/ }), -/* 131 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _domUtils = __webpack_require__(4); - -var _domUtils2 = _interopRequireDefault(_domUtils); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Bold - * Add bold to selected wysiwyg editor content - * @extends Command - * @module wysiwygCommands/Bold - * @ignore - */ -/** - * @fileoverview Implements bold WysiwygCommand - * @author NHN FE Development Lab - */ -var Bold = _commandManager2.default.command('wysiwyg', /** @lends Bold */{ - name: 'Bold', - keyMap: ['CTRL+B', 'META+B'], - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var tableSelectionManager = wwe.componentManager.getManager('tableSelection'); - - wwe.focus(); - - if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) { - tableSelectionManager.styleToSelectedCells(styleBold); - - var range = sq.getSelection(); - range.collapse(true); - sq.setSelection(range); - } else { - styleBold(sq); - _domUtils2.default.optimizeRange(sq.getSelection(), 'B'); - } - } -}); - -/** - * Style bold. - * @param {object} sq - squire editor instance - */ -function styleBold(sq) { - if (sq.hasFormat('b') || sq.hasFormat('strong')) { - sq.changeFormat(null, { tag: 'b' }); - } else if (!sq.hasFormat('PRE')) { - if (sq.hasFormat('code')) { - sq.changeFormat(null, { tag: 'code' }); - } - sq.bold(); - } -} - -exports.default = Bold; - -/***/ }), -/* 132 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _domUtils = __webpack_require__(4); - -var _domUtils2 = _interopRequireDefault(_domUtils); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Italic - * Add Italic to selected wysiwyg editor content - * @extends Command - * @module wysiwygCommands/Italic - * @ignore - */ -/** - * @fileoverview Implements italic WysiwygCommand - * @author NHN FE Development Lab - */ - -var Italic = _commandManager2.default.command('wysiwyg', /** @lends Italic */{ - name: 'Italic', - keyMap: ['CTRL+I', 'META+I'], - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var tableSelectionManager = wwe.componentManager.getManager('tableSelection'); - - wwe.focus(); - - if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) { - tableSelectionManager.styleToSelectedCells(styleItalic); - - var range = sq.getSelection(); - range.collapse(true); - sq.setSelection(range); - } else { - styleItalic(sq); - _domUtils2.default.optimizeRange(sq.getSelection(), 'I'); - } - } -}); - -/** - * Style italic. - * @param {object} sq - squire editor instance - */ -function styleItalic(sq) { - if (sq.hasFormat('i') || sq.hasFormat('em')) { - sq.changeFormat(null, { tag: 'i' }); - } else if (!sq.hasFormat('PRE')) { - if (sq.hasFormat('code')) { - sq.changeFormat(null, { tag: 'code' }); - } - sq.italic(); - } -} - -exports.default = Italic; - -/***/ }), -/* 133 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _domUtils = __webpack_require__(4); - -var _domUtils2 = _interopRequireDefault(_domUtils); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Strike - * Add strike to selected wysiwyg editor content - * @extends Command - * @module wysiwygCommands/Strike - * @ignore - */ -/** - * @fileoverview Implements strike WysiwygCommand - * @author NHN FE Development Lab - */ - -var Strike = _commandManager2.default.command('wysiwyg', /** @lends Strike */{ - name: 'Strike', - keyMap: ['CTRL+S', 'META+S'], - /** - * command handler - * @param {WysiwygEditor} wwe WysiwygEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var tableSelectionManager = wwe.componentManager.getManager('tableSelection'); - - wwe.focus(); - - if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) { - tableSelectionManager.styleToSelectedCells(styleStrike); - - var range = sq.getSelection(); - range.collapse(true); - sq.setSelection(range); - } else { - styleStrike(sq); - _domUtils2.default.optimizeRange(sq.getSelection(), 'S'); - } - } -}); - -/** - * Style strike. - * @param {object} sq - squire editor instance - */ -function styleStrike(sq) { - if (sq.hasFormat('S')) { - sq.changeFormat(null, { tag: 'S' }); - } else if (!sq.hasFormat('PRE')) { - if (sq.hasFormat('code')) { - sq.changeFormat(null, { tag: 'code' }); - } - sq.strikethrough(); - } -} - -exports.default = Strike; - -/***/ }), -/* 134 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Blockquote - * Add Blockquote to selected wysiwyg editor content - * @extends Command - * @module wysiwygCommands/Blockquote - * @ignore - */ -var Blockquote = _commandManager2.default.command('wysiwyg', /** @lends Blockquote */{ - name: 'Blockquote', - keyMap: ['ALT+Q', 'ALT+Q'], - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - - wwe.focus(); - - if (!sq.hasFormat('TABLE') && !sq.hasFormat('PRE')) { - if (sq.hasFormat('BLOCKQUOTE')) { - sq.decreaseQuoteLevel(); - } else { - sq.increaseQuoteLevel(); - } - } - } -}); /** - * @fileoverview Implements block quote WysiwygCommand - * @author NHN FE Development Lab - */ - -exports.default = Blockquote; - -/***/ }), -/* 135 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _importManager = __webpack_require__(15); - -var _importManager2 = _interopRequireDefault(_importManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview Implements AddImage wysiwyg command - * @author NHN FE Development Lab - */ -var decodeURIGraceful = _importManager2.default.decodeURIGraceful, - encodeMarkdownCharacters = _importManager2.default.encodeMarkdownCharacters; - -/** - * AddImage - * Add Image markdown syntax to wysiwyg Editor - * @extends Command - * @module wysiwygCommands/AddImage - * @ignore - */ - -var AddImage = _commandManager2.default.command('wysiwyg', /** @lends AddImage */{ - name: 'AddImage', - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - * @param {object} data data for image - */ - exec: function exec(wwe, data) { - var sq = wwe.getEditor(); - var altText = data.altText, - imageUrl = data.imageUrl; - - altText = decodeURIGraceful(altText); - imageUrl = encodeMarkdownCharacters(imageUrl); - - wwe.focus(); - - if (!sq.hasFormat('PRE')) { - sq.insertImage(imageUrl, { 'alt': altText }); - } - } -}); - -exports.default = AddImage; - -/***/ }), -/* 136 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _importManager = __webpack_require__(15); - -var _importManager2 = _interopRequireDefault(_importManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview Implements AddLink wysiwyg command - * @author NHN FE Development Lab - */ -var decodeURIGraceful = _importManager2.default.decodeURIGraceful, - encodeMarkdownCharacters = _importManager2.default.encodeMarkdownCharacters; - -/** - * AddLink - * Add link markdown syntax to wysiwyg Editor - * @extends Command - * @module wysiwygCommands/AddLink - * @ignore - */ - -var AddLink = _commandManager2.default.command('wysiwyg', /** @lends AddLink */{ - name: 'AddLink', - /** - * command handler - * @param {WysiwygEditor} wwe - wysiwygEditor instance - * @param {object} data - data for image - */ - exec: function exec(wwe, data) { - var sq = wwe.getEditor(); - var linkAttibute = wwe.getLinkAttribute(); - var url = data.url, - linkText = data.linkText; - - linkText = decodeURIGraceful(linkText); - url = encodeMarkdownCharacters(url); - - wwe.focus(); - - if (!sq.hasFormat('PRE')) { - sq.removeAllFormatting(); - - if (sq.getSelectedText()) { - sq.makeLink(url, linkAttibute); - } else { - var link = sq.createElement('A', _tuiCodeSnippet2.default.extend({ - href: url - }, linkAttibute)); - - (0, _jquery2.default)(link).text(linkText); - sq.insertElement(link); - } - } - } -}); - -exports.default = AddLink; - -/***/ }), -/* 137 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _domUtils = __webpack_require__(4); - -var _domUtils2 = _interopRequireDefault(_domUtils); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * HR - * Add horizontal line markdown syntax to wysiwyg Editor - * @extends Command - * @module wysiwygCommands/HR - * @ignore - */ -/** - * @fileoverview Implements HR wysiwyg command - * @author NHN FE Development Lab - */ -var HR = _commandManager2.default.command('wysiwyg', /** @lends HR */{ - name: 'HR', - keyMap: ['CTRL+L', 'META+L'], - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var range = sq.getSelection(); - - if (range.collapsed && !sq.hasFormat('TABLE') && !sq.hasFormat('PRE')) { - var hr = document.createElement('hr'); - var currentNode = _domUtils2.default.getChildNodeByOffset(range.startContainer, range.startOffset); - var nextBlockNode = _domUtils2.default.getTopNextNodeUnder(currentNode, wwe.get$Body()[0]); - - // If nextBlockNode is div that has hr and has contenteditable as false, - // nextBlockNode should be set as nextSibling that is normal block. - if (nextBlockNode && !_domUtils2.default.isTextNode(nextBlockNode)) { - while (nextBlockNode && nextBlockNode.getAttribute('contenteditable') === 'false') { - nextBlockNode = nextBlockNode.nextSibling; - } - } - - if (!nextBlockNode) { - nextBlockNode = _domUtils2.default.createEmptyLine(); - wwe.get$Body().append(nextBlockNode); - } - - sq.modifyBlocks(function (frag) { - frag.appendChild(hr); - - return frag; - }); - - var previousSibling = hr.previousSibling; - - if (previousSibling && _domUtils2.default.isTextNode(previousSibling) && _domUtils2.default.getTextLength(previousSibling) === 0) { - hr.parentNode.removeChild(previousSibling); - } - - hr.parentNode.replaceChild(_domUtils2.default.createHorizontalRule(), hr); - - range.selectNodeContents(nextBlockNode); - range.collapse(true); - - sq.setSelection(range); - sq.saveUndoState(range); - } - - wwe.focus(); - } -}); - -exports.default = HR; - -/***/ }), -/* 138 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Heading - * Convert selected root level contents to heading with size wysiwyg Editor - * @extends Command - * @module wysiwygCommands/Heading - * @ignore - */ -/** - * @fileoverview Implements Heading wysiwyg command - * @author NHN FE Development Lab - */ -var Heading = _commandManager2.default.command('wysiwyg', /** @lends Heading */{ - name: 'Heading', - /** - * Command handler - * @param {WysiwygEditor} wwe WYSIWYGEditor instance - * @param {Number} size size - */ - exec: function exec(wwe, size) { - var sq = wwe.getEditor(); - var blockTagName = 'h1, h2, h3, h4, h5, h6, div'; - - wwe.focus(); - - if (!sq.hasFormat('TABLE') && !sq.hasFormat('PRE')) { - sq.modifyBlocks(function (fragment) { - (0, _jquery2.default)(fragment).children(blockTagName).each(function (index, block) { - var headingHTML = ''; - var $block = (0, _jquery2.default)(block); - - if ($block.is('DIV')) { - $block.wrap(headingHTML); - } else { - var $wrapperHeading = (0, _jquery2.default)(headingHTML); - - $wrapperHeading.insertBefore(block); - $wrapperHeading.html($block.html()); - $block.remove(); - } - }); - - return fragment; - }); - } - } -}); - -exports.default = Heading; - -/***/ }), -/* 139 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Paragraph - * Convert selected contents to paragraph only heading and list - * @extends Command - * @module wysiwygCommands/Paragraph - * @ignore - */ -/** - * @fileoverview Implements Paragraph wysiwyg command - * @author NHN FE Development Lab - */ -var Paragraph = _commandManager2.default.command('wysiwyg', /** @lends Paragraph */{ - name: 'Paragraph', - /** - * Command handler - * @param {WysiwygEditor} wwe WYSIWYGEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - - wwe.focus(); - - if (!sq.hasFormat('TABLE') && !sq.hasFormat('PRE')) { - sq.modifyBlocks(function (fragment) { - var $newFragment = (0, _jquery2.default)(document.createDocumentFragment()); - - (0, _jquery2.default)(fragment).children().each(function (index, block) { - if (block.nodeName.match(/h\d/i)) { - $newFragment.append((0, _jquery2.default)(block).children()); - } else if (block.nodeName.match(/ul|ol/i)) { - (0, _jquery2.default)(block).find('li').each(function (i, listItem) { - $newFragment.append((0, _jquery2.default)(listItem).children()); - }); - } else { - $newFragment.append(block); - } - }); - - return $newFragment[0]; - }); - } - } -}); - -exports.default = Paragraph; - -/***/ }), -/* 140 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * UL - * Add UL to selected wysiwyg editor content - * @extends Command - * @module wysiwygCommands/UL - * @ignore - */ -var UL = _commandManager2.default.command('wysiwyg', /** @lends UL */{ - name: 'UL', - keyMap: ['CTRL+U', 'META+U'], - /** - * Command Handler - * @param {WysiwygEditor} wwe WYSIWYGEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var range = sq.getSelection(); - var listManager = wwe.componentManager.getManager('list'); - var startContainer = range.startContainer, - endContainer = range.endContainer, - startOffset = range.startOffset, - endOffset = range.endOffset; - - var newLIs = []; - - wwe.focus(); - sq.saveUndoState(range); - - if (listManager.isAvailableMakeListInTable()) { - newLIs = listManager.createListInTable(range, 'UL'); - } else { - var lines = listManager.getLinesOfSelection(startContainer, endContainer); - - for (var i = 0; i < lines.length; i += 1) { - var newLI = this._changeFormatToUnorderedListIfNeed(wwe, lines[i]); - if (newLI) { - newLIs.push(newLI); - } - } - } - - if (newLIs.length) { - listManager.adjustRange(startContainer, endContainer, startOffset, endOffset, newLIs); - } - }, - - - /** - * Change format to unordered list if need - * @param {WysiwygEditor} wwe Wysiwyg editor instance - * @param {HTMLElement} target Element target for change - * @returns {HTMLElement} newly created list - * @private - */ - _changeFormatToUnorderedListIfNeed: function _changeFormatToUnorderedListIfNeed(wwe, target) { - var sq = wwe.getEditor(); - var range = sq.getSelection(); - var taskManager = wwe.componentManager.getManager('task'); - var newLI = void 0; - - if (!sq.hasFormat('PRE')) { - range.setStart(target, 0); - range.collapse(true); - sq.setSelection(range); - - if (sq.hasFormat('LI')) { - wwe.saveSelection(range); - taskManager.unformatTask(range.startContainer); - sq.replaceParent(range.startContainer, 'ol', 'ul'); - wwe.restoreSavedSelection(); - } else { - wwe.unwrapBlockTag(); - sq.makeUnorderedList(); - } - - newLI = sq.getSelection().startContainer; - } - - return newLI; - } -}); /** - * @fileoverview Implements ul WysiwygCommand - * @author NHN FE Development Lab - */ -exports.default = UL; - -/***/ }), -/* 141 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * OL - * Add OL to selected wysiwyg editor content - * @extends Command - * @module wysiwygCommands/OL - * @ignore - */ -var OL = _commandManager2.default.command('wysiwyg', /** @lends OL */{ - name: 'OL', - keyMap: ['CTRL+O', 'META+O'], - /** - * Command Handler - * @param {WysiwygEditor} wwe WYSIWYGEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var range = sq.getSelection(); - var listManager = wwe.componentManager.getManager('list'); - var startContainer = range.startContainer, - startOffset = range.startOffset, - endContainer = range.endContainer, - endOffset = range.endOffset; - - var newLIs = []; - - wwe.focus(); - sq.saveUndoState(range); - - if (listManager.isAvailableMakeListInTable()) { - newLIs = listManager.createListInTable(range, 'OL'); - } else { - var lines = listManager.getLinesOfSelection(startContainer, endContainer); - - for (var i = 0; i < lines.length; i += 1) { - var newLI = this._changeFormatToOrderedListIfNeed(wwe, lines[i]); - if (newLI) { - newLIs.push(newLI); - } - } - } - - if (newLIs.length) { - listManager.adjustRange(startContainer, endContainer, startOffset, endOffset, newLIs); - } - }, - - - /** - * Change format to unordered list if need - * @param {WysiwygEditor} wwe Wysiwyg editor instance - * @param {HTMLElement} target Element target for change - * @returns {HTMLElement} newly created list item - * @private - */ - _changeFormatToOrderedListIfNeed: function _changeFormatToOrderedListIfNeed(wwe, target) { - var sq = wwe.getEditor(); - var range = sq.getSelection(); - var taskManager = wwe.componentManager.getManager('task'); - var newLI = void 0; - - if (!sq.hasFormat('PRE')) { - range.setStart(target, 0); - range.collapse(true); - sq.setSelection(range); - - if (sq.hasFormat('LI')) { - wwe.saveSelection(range); - taskManager.unformatTask(range.startContainer); - sq.replaceParent(range.startContainer, 'ul', 'ol'); - wwe.restoreSavedSelection(); - } else { - wwe.unwrapBlockTag(); - sq.makeOrderedList(); - } - - newLI = sq.getSelection().startContainer; - } - - return newLI; - } -}); /** - * @fileoverview Implements ol WysiwygCommand - * @author NHN FE Development Lab - */ - -exports.default = OL; - -/***/ }), -/* 142 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Table - * Add table to selected wysiwyg editor content - * @extends Command - * @module wysiwygCommands/Table - * @ignore - */ -var Table = _commandManager2.default.command('wysiwyg', /** @lends Table */{ - name: 'Table', - /** - * Command Handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - * @param {number} col column count - * @param {number} row row count - * @param {Array} data initial table data - */ - exec: function exec(wwe, col, row, data) { - var sq = wwe.getEditor(); - var tableIDClassName = wwe.componentManager.getManager('table').getTableIDClassName(); - var tableHTMLString = void 0; - - if (!sq.getSelection().collapsed || sq.hasFormat('TABLE') || sq.hasFormat('PRE')) { - wwe.focus(); - - return; - } - - tableHTMLString = ''; - tableHTMLString += makeHeader(col, data); - tableHTMLString += makeBody(col, row - 1, data); - tableHTMLString += '
    '; - - sq.insertHTML(tableHTMLString); - - wwe.focus(); - - if (!data) { - focusToFirstTh(sq, wwe.get$Body().find('.' + tableIDClassName)); - } - } -}); - -/** - * Focus to first th - * @param {Squire} sq Squire instance - * @param {jQuery} $table jQuery wrapped table element - */ -/** - * @fileoverview Implements table WysiwygCommand - * @author NHN FE Development Lab - */ -function focusToFirstTh(sq, $table) { - var range = sq.getSelection(); - - range.selectNodeContents($table.find('th')[0]); - range.collapse(true); - sq.setSelection(range); -} - -/** - * makeHeader - * make table header html string - * @param {number} col column count - * @param {string} data cell data - * @returns {string} html string - */ -function makeHeader(col, data) { - var header = ''; - var index = 0; - - while (col) { - header += ''; - - if (data) { - header += data[index]; - index += 1; - } - - header += ''; - col -= 1; - } - - header += ''; - - return header; -} - -/** - * makeBody - * make table body html string - * @param {number} col column count - * @param {number} row row count - * @param {string} data cell data - * @returns {string} html string - */ -function makeBody(col, row, data) { - var body = ''; - var index = col; - - for (var irow = 0; irow < row; irow += 1) { - body += ''; - - for (var icol = 0; icol < col; icol += 1) { - body += ''; - - if (data) { - body += data[index]; - index += 1; - } - - body += ''; - } - - body += ''; - } - - body += ''; - - return body; -} - -exports.default = Table; - -/***/ }), -/* 143 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * AddRow - * Add Row to selected table - * @extends Command - * @module wysiwygCommands/TableAddRow - * @ignore - */ -var TableAddRow = _commandManager2.default.command('wysiwyg', /** @lends AddRow */{ - name: 'AddRow', - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var range = sq.getSelection().cloneRange(); - var selectedRowLength = getSelectedRowsLength(wwe); - var $tr = void 0, - $newRow = void 0; - - wwe.focus(); - - if (sq.hasFormat('TD')) { - sq.saveUndoState(range); - $tr = (0, _jquery2.default)(range.startContainer).closest('tr'); - for (var i = 0; i < selectedRowLength; i += 1) { - $newRow = getNewRow($tr); - $newRow.insertAfter($tr); - } - - focusToFirstTd(sq, $newRow); - } else if (sq.hasFormat('TH')) { - sq.saveUndoState(range); - $tr = (0, _jquery2.default)(range.startContainer).parents('thead').next('tbody').children('tr').eq(0); - for (var _i = 0; _i < selectedRowLength; _i += 1) { - $newRow = getNewRow($tr); - $newRow.insertBefore($tr); - } - - focusToFirstTd(sq, $newRow); - } - } -}); - -/** - * get number of selected rows - * @param {WysiwygEditor} wwe - wysiwygEditor instance - * @returns {number} - number of selected rows - * @ignore - */ -/** - * @fileoverview Implements table add row WysiwygCommand - * @author NHN FE Development Lab - */ -function getSelectedRowsLength(wwe) { - var selectionMgr = wwe.componentManager.getManager('tableSelection'); - var $selectedCells = selectionMgr.getSelectedCells(); - var length = 1; - - if ($selectedCells.length > 1) { - var first = $selectedCells.first().get(0); - var last = $selectedCells.last().get(0); - var range = selectionMgr.getSelectionRangeFromTable(first, last); - length = range.to.row - range.from.row + 1; - } - - return length; -} - -/** - * Get new row of given row - * @param {jQuery} $tr - jQuery wrapped table row - * @returns {jQuery} - new cloned jquery element - * @ignore - */ -function getNewRow($tr) { - var cloned = $tr.clone(); - var htmlString = _tuiCodeSnippet2.default.browser.msie ? '' : '
    '; - - cloned.find('td').html(htmlString); - - return cloned; -} - -/** - * Focus to first table cell - * @param {Squire} sq - Squire instance - * @param {jQuery} $tr - jQuery wrapped table row - * @ignore - */ -function focusToFirstTd(sq, $tr) { - var range = sq.getSelection(); - - range.selectNodeContents($tr.find('td')[0]); - range.collapse(true); - sq.setSelection(range); -} - -exports.default = TableAddRow; - -/***/ }), -/* 144 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _domUtils = __webpack_require__(4); - -var _domUtils2 = _interopRequireDefault(_domUtils); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * AddCol - * Add col to selected table - * @extends Command - * @module wysiwygCommands/TableAddCol - * @ignore - */ -/** - * @fileoverview Implements table add column WysiwygCommand - * @author NHN FE Development Lab - */ -var TableAddCol = _commandManager2.default.command('wysiwyg', /** @lends AddCol */{ - name: 'AddCol', - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var range = sq.getSelection().cloneRange(); - var numberOfCols = getNumberOfCols(wwe); - var $cell = void 0; - - wwe.focus(); - - if (sq.hasFormat('TR')) { - sq.saveUndoState(range); - - $cell = getCellByRange(range); - addColToCellAfter($cell, numberOfCols); - - focusToNextCell(sq, $cell); - } - } -}); - -/** - * get number of selected cols - * @param {WysiwygEditor} wwe - wysiwyg editor instance - * @returns {number} - number of selected cols - * @ignore - */ -function getNumberOfCols(wwe) { - var selectionMgr = wwe.componentManager.getManager('tableSelection'); - var $selectedCells = selectionMgr.getSelectedCells(); - var length = 1; - - if ($selectedCells.length > 0) { - var maxLength = $selectedCells.get(0).parentNode.querySelectorAll('td, th').length; - length = Math.min(maxLength, $selectedCells.length); - } - - return length; -} - -/** - * Get cell by range object - * @param {Range} range - range - * @returns {jQuery} - jQuery html element - * @ignore - */ -function getCellByRange(range) { - var cell = range.startContainer; - - if (_domUtils2.default.getNodeName(cell) === 'TD' || _domUtils2.default.getNodeName(cell) === 'TH') { - cell = (0, _jquery2.default)(cell); - } else { - cell = (0, _jquery2.default)(cell).parentsUntil('tr'); - } - - return cell; -} - -/** - * Add column to after the current cell - * @param {jQuery} $cell - jQuery wrapped table cell - * @param {number} [numberOfCols=1] - number of cols - * @ignore - */ -function addColToCellAfter($cell) { - var numberOfCols = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; - - var index = $cell.index(); - var cellToAdd = void 0; - - $cell.parents('table').find('tr').each(function (n, tr) { - var isTBody = _domUtils2.default.getNodeName(tr.parentNode) === 'TBODY'; - var isMSIE = _tuiCodeSnippet2.default.browser.msie; - var cell = tr.children[index]; - for (var i = 0; i < numberOfCols; i += 1) { - if (isTBody) { - cellToAdd = document.createElement('td'); - } else { - cellToAdd = document.createElement('th'); - } - if (!isMSIE) { - cellToAdd.appendChild(document.createElement('br')); - } - (0, _jquery2.default)(cellToAdd).insertAfter(cell); - } - }); -} - -/** - * Focus to next cell - * @param {Squire} sq - Squire instance - * @param {jQuery} $cell - jQuery wrapped table cell - * @ignore - */ -function focusToNextCell(sq, $cell) { - var range = sq.getSelection(); - - range.selectNodeContents($cell.next()[0]); - range.collapse(true); - - sq.setSelection(range); -} - -exports.default = TableAddCol; - -/***/ }), -/* 145 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * RemoveRow - * remove Row to selected table - * @extends Command - * @module wysiwygCommands/TableRemoveRow - * @ignore - */ -/** - * @fileoverview Implements table remove row WysiwygCommand - * @author NHN FE Development Lab - */ -var TableRemoveRow = _commandManager2.default.command('wysiwyg', /** @lends RemoveRow */{ - name: 'RemoveRow', - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var range = sq.getSelection().cloneRange(); - var $table = (0, _jquery2.default)(range.startContainer).parents('table'); - var selectionMgr = wwe.componentManager.getManager('tableSelection'); - var tableMgr = wwe.componentManager.getManager('table'); - var $tr = getTrs(range, selectionMgr, $table); - var tbodyRowLength = $table.find('tbody tr').length; - - wwe.focus(); - - if ((sq.hasFormat('TD') || sq.hasFormat('TABLE')) && tbodyRowLength > 1) { - sq.saveUndoState(range); - var $nextFocus = $tr.last().next()[0] ? $tr.last().next() : $tr.first().prev(); - - if ($nextFocus.length) { - focusToFirstTd(sq, range, $nextFocus, tableMgr); - } - $tr.remove(); - } - selectionMgr.removeClassAttrbuteFromAllCellsIfNeed(); - } -}); - -/** - * Focus to first TD in given TR - * @param {SquireExt} sq Squire instance - * @param {Range} range Range object - * @param {jQuery} $tr jQuery wrapped TR - * @param {object} tableMgr Table manager - */ -function focusToFirstTd(sq, range, $tr, tableMgr) { - var nextFocusCell = $tr.find('td').get(0); - range.setStart(nextFocusCell, 0); - range.collapse(true); - - tableMgr.setLastCellNode(nextFocusCell); - sq.setSelection(range); -} - -/** - * Get start, end row index from current range - * @param {HTMLElement} firstSelectedCell Range object - * @param {object} rangeInformation Range information object - * @param {jQuery} $table jquery wrapped TABLE - * @returns {jQuery} - */ -function getSelectedRows(firstSelectedCell, rangeInformation, $table) { - var tbodyRowLength = $table.find('tbody tr').length; - var isStartContainerInThead = (0, _jquery2.default)(firstSelectedCell).parents('thead').length; - var startRowIndex = rangeInformation.from.row; - var endRowIndex = rangeInformation.to.row; - - if (isStartContainerInThead) { - startRowIndex += 1; - } - - var isWholeTbodySelected = (startRowIndex === 1 || isStartContainerInThead) && endRowIndex === tbodyRowLength; - - if (isWholeTbodySelected) { - endRowIndex -= 1; - } - - return $table.find('tr').slice(startRowIndex, endRowIndex + 1); -} - -/** - * Get TRs - * @param {Range} range Range object - * @param {object} selectionMgr Table selection manager - * @param {jQuery} $table current table - * @returns {jQuery} - */ -function getTrs(range, selectionMgr, $table) { - var $selectedCells = selectionMgr.getSelectedCells(); - var rangeInformation = void 0, - trs = void 0; - - if ($selectedCells.length) { - rangeInformation = selectionMgr.getSelectionRangeFromTable($selectedCells.first().get(0), $selectedCells.last().get(0)); - trs = getSelectedRows($selectedCells.first()[0], rangeInformation, $table); - } else { - var cell = (0, _jquery2.default)(range.startContainer).closest('td,th').get(0); - rangeInformation = selectionMgr.getSelectionRangeFromTable(cell, cell); - trs = getSelectedRows(cell, rangeInformation, $table); - } - - return trs; -} -exports.default = TableRemoveRow; - -/***/ }), -/* 146 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _domUtils = __webpack_require__(4); - -var _domUtils2 = _interopRequireDefault(_domUtils); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * RemoveCol - * remove Row to selected table - * @extends Command - * @module wysiwygCommands/TableRemoveCol - * @ignore - */ -var TableRemoveCol = _commandManager2.default.command('wysiwyg', /** @lends RemoveCol */{ - name: 'RemoveCol', - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var range = sq.getSelection().cloneRange(); - var $table = (0, _jquery2.default)(range.startContainer).parents('table'); - var tableMgr = wwe.componentManager.getManager('table'); - var selectionMgr = wwe.componentManager.getManager('tableSelection'); - var hasMultipleCols = (0, _jquery2.default)(range.startContainer).closest('table').find('thead tr th').length > 1; - - wwe.focus(); - // IE 800a025e error on removing part of selection range. collapse - range.collapse(true); - sq.setSelection(range); - - if (sq.hasFormat('TR', null, range) && hasMultipleCols) { - var tbodyColLength = $table.find('tbody tr:first td').length; - var $selectedCellsByManager = selectionMgr.getSelectedCells(); - - if ($selectedCellsByManager.length < tbodyColLength) { - sq.saveUndoState(range); - var $nextFocus = void 0; - - if ($selectedCellsByManager.length > 1) { - var $tailCell = $selectedCellsByManager.last(); - var $headCell = $selectedCellsByManager.first(); - $nextFocus = $tailCell.next().length ? $tailCell.next() : $headCell.prev(); - - removeMultipleColsByCells($selectedCellsByManager); - } else { - var $cell = getCellByRange(range); - $nextFocus = $cell.next().length ? $cell.next() : $cell.prev(); - - removeColByCell($cell); - } - - focusToCell(sq, $nextFocus, tableMgr); - } - } - } -}); - -/** - * Get cell by range object - * @param {Range} range range - * @returns {HTMLElement|Node} - */ -/** - * @fileoverview Implements table remove column WysiwygCommand - * @author NHN FE Development Lab - */ -function getCellByRange(range) { - var cell = range.startContainer; - - if (_domUtils2.default.getNodeName(cell) === 'TD' || _domUtils2.default.getNodeName(cell) === 'TH') { - cell = (0, _jquery2.default)(cell); - } else { - cell = (0, _jquery2.default)(cell).parentsUntil('tr'); - } - - return cell; -} - -/** - * Remove columns by given cells - * @param {jQuery} $cells - jQuery table cells - */ -function removeMultipleColsByCells($cells) { - var numberOfCells = $cells.length; - for (var i = 0; i < numberOfCells; i += 1) { - var $cellToDelete = $cells.eq(i); - if ($cellToDelete.length > 0) { - removeColByCell($cells.eq(i)); - } - } -} - -/** - * Remove column by given cell - * @param {jQuery} $cell - jQuery wrapped table cell - */ -function removeColByCell($cell) { - var index = $cell.index(); - - $cell.parents('table').find('tr').each(function (n, tr) { - (0, _jquery2.default)(tr).children().eq(index).remove(); - }); -} - -/** - * Focus to given cell - * @param {Squire} sq - Squire instance - * @param {jQuery} $cell - jQuery wrapped table cell - * @param {object} tableMgr - Table manager instance - */ -function focusToCell(sq, $cell, tableMgr) { - var nextFocusCell = $cell.get(0); - - if ($cell.length && _jquery2.default.contains(document, $cell)) { - var range = sq.getSelection(); - range.selectNodeContents($cell[0]); - range.collapse(true); - sq.setSelection(range); - - tableMgr.setLastCellNode(nextFocusCell); - } -} - -exports.default = TableRemoveCol; - -/***/ }), -/* 147 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _domUtils = __webpack_require__(4); - -var _domUtils2 = _interopRequireDefault(_domUtils); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * AlignCol - * Align selected column's text content to given direction - * @extends Command - * @module wysiwygCommands/TableAlignCol - * @ignore - */ -var TableAlignCol = _commandManager2.default.command('wysiwyg', /** @lends AlignCol */{ - name: 'AlignCol', - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - * @param {string} alignDirection Align direction - */ - exec: function exec(wwe, alignDirection) { - var sq = wwe.getEditor(); - var range = sq.getSelection().cloneRange(); - var selectionMgr = wwe.componentManager.getManager('tableSelection'); - var rangeInformation = getRangeInformation(range, selectionMgr); - - wwe.focus(); - - if (sq.hasFormat('TR')) { - sq.saveUndoState(range); - - var $table = (0, _jquery2.default)(range.startContainer).parents('table'); - - var selectionInformation = getSelectionInformation($table, rangeInformation); - - setAlignAttributeToTableCells($table, alignDirection, selectionInformation); - } - selectionMgr.removeClassAttrbuteFromAllCellsIfNeed(); - } -}); - -/** - * Set Column align - * @param {jQuery} $table jQuery wrapped TABLE - * @param {string} alignDirection 'left' or 'center' or 'right' - * @param {{ - * startColumnIndex: number, - * endColumnIndex: number, - * isDivided: boolean - * }} selectionInformation start, end column index and boolean value for whether range divided or not - */ -/** - * @fileoverview Implements table align column WysiwygCommand - * @author NHN FE Development Lab - */ -function setAlignAttributeToTableCells($table, alignDirection, selectionInformation) { - var isDivided = selectionInformation.isDivided || false; - var start = selectionInformation.startColumnIndex; - var end = selectionInformation.endColumnIndex; - var columnLength = $table.find('tr').eq(0).find('td,th').length; - - $table.find('tr').each(function (n, tr) { - (0, _jquery2.default)(tr).children('td,th').each(function (index, cell) { - if (isDivided && (start <= index && index <= columnLength || index <= end)) { - (0, _jquery2.default)(cell).attr('align', alignDirection); - } else if (start <= index && index <= end) { - (0, _jquery2.default)(cell).attr('align', alignDirection); - } - }); - }); -} - -/** - * Return start, end column index and boolean value for whether range divided or not - * @param {jQuery} $table jQuery wrapped TABLE - * @param {{startColumnIndex: number, endColumnIndex: number}} rangeInformation Range information - * @returns {{startColumnIndex: number, endColumnIndex: number, isDivided: boolean}} - */ -function getSelectionInformation($table, rangeInformation) { - var columnLength = $table.find('tr').eq(0).find('td,th').length; - var from = rangeInformation.from, - to = rangeInformation.to; - - var startColumnIndex = void 0, - endColumnIndex = void 0, - isDivided = void 0; - - if (from.row === to.row) { - startColumnIndex = from.cell; - endColumnIndex = to.cell; - } else if (from.row < to.row) { - if (from.cell <= to.cell) { - startColumnIndex = 0; - endColumnIndex = columnLength - 1; - } else { - startColumnIndex = from.cell; - endColumnIndex = to.cell; - isDivided = true; - } - } - - return { - startColumnIndex: startColumnIndex, - endColumnIndex: endColumnIndex, - isDivided: isDivided - }; -} - -/** - * Get range information - * @param {Range} range Range object - * @param {object} selectionMgr Table selection manager - * @returns {object} - */ -function getRangeInformation(range, selectionMgr) { - var $selectedCells = selectionMgr.getSelectedCells(); - var rangeInformation = void 0, - startCell = void 0; - - if ($selectedCells.length) { - rangeInformation = selectionMgr.getSelectionRangeFromTable($selectedCells.first().get(0), $selectedCells.last().get(0)); - } else { - var startContainer = range.startContainer; - - startCell = _domUtils2.default.isTextNode(startContainer) ? (0, _jquery2.default)(startContainer).parent('td,th')[0] : startContainer; - rangeInformation = selectionMgr.getSelectionRangeFromTable(startCell, startCell); - } - - return rangeInformation; -} - -exports.default = TableAlignCol; - -/***/ }), -/* 148 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * RemoveTable - * Remove selected table - * @extends Command - * @module wysiwygCommands/TableRemove - * @ignore - */ -/** - * @fileoverview Implements table remove WysiwygCommand - * @author NHN FE Development Lab - */ -var TableRemove = _commandManager2.default.command('wysiwyg', /** @lends RemoveTable */{ - name: 'RemoveTable', - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var range = sq.getSelection().cloneRange(); - - if (sq.hasFormat('TABLE')) { - sq.saveUndoState(range); - var $table = (0, _jquery2.default)(range.startContainer).closest('table'); - - $table.remove(); - } - - wwe.focus(); - } -}); - -exports.default = TableRemove; - -/***/ }), -/* 149 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Indent - * Indent list or task to wysiwyg Editor - * @extends Command - * @module wysiwygCommands/indent - * @ignore - */ -/** - * @fileoverview Implements Indent wysiwyg command - * @author NHN FE Development Lab - */ -var Indent = _commandManager2.default.command('wysiwyg', /** @lends Indent */{ - name: 'Indent', - /** - * Command Handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - */ - exec: function exec(wwe) { - var listManager = wwe.componentManager.getManager('list'); - var range = wwe.getEditor().getSelection(); - var $node = (0, _jquery2.default)(range.startContainer).closest('li'); - var prevClasses = void 0, - nodeClasses = void 0, - nextClasses = void 0; - - var $prev = $node.prev(); - - if ($prev.length && $node.length) { - var $next = $node.find('li').eq(0); - - wwe.getEditor().saveUndoState(); - - nodeClasses = $node.attr('class'); - prevClasses = $prev.attr('class'); - nextClasses = $next.attr('class'); - - $node.removeAttr('class'); - $prev.removeAttr('class'); - - if ($next.length && !$next.children('div').length) { - $next.removeAttr('class'); - } - - wwe.getEditor().increaseListLevel(); - listManager.mergeList($node.get(0)); - - $node.attr('class', nodeClasses); - $prev.attr('class', prevClasses); - $next.attr('class', nextClasses); - } - } -}); - -exports.default = Indent; - -/***/ }), -/* 150 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Outdent - * Outdent list or task to wysiwyg Editor - * @extends Command - * @module wysiwygCommands/Outdent - * @ignore - */ -/** - * @fileoverview Implements Outdent wysiwyg command - * @author NHN FE Development Lab - */ -var Outdent = _commandManager2.default.command('wysiwyg', /** @lends Outdent */{ - name: 'Outdent', - - /** - * Command Handler - * @param {WysiwygEditor} wwe WysiwygEditor instance - */ - exec: function exec(wwe) { - var $node = getCurrent$Li(wwe); - - if ($node.length && isExecutable($node)) { - wwe.getEditor().saveUndoState(); - - var nodeClasses = $node.attr('class'); - wwe.getEditor().decreaseListLevel(); - - $node = getCurrent$Li(wwe); - $node.attr('class', nodeClasses); - } - } -}); - -/** - * test if outdent the given list item - * arbitrary list allows list item to be in any position - * while markdown spec does not - * @param {jQuery} $currentLiNode - jQuery list item element - * @returns {boolean} - true to executable - * @ignore - */ -function isExecutable($currentLiNode) { - return !$currentLiNode.next().is('OL,UL'); -} - -/** - * Get list item element of current selection - * @param {object} wwe Wysiwyg editor instance - * @returns {jQuery} - * @ignore - */ -function getCurrent$Li(wwe) { - var range = wwe.getEditor().getSelection(); - - return (0, _jquery2.default)(range.startContainer).closest('li'); -} - -exports.default = Outdent; - -/***/ }), -/* 151 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Task - * Add Task to selected wysiwyg editor content - * @extends Command - * @module wysiwygCommands/Task - * @ignore - */ -/** - * @fileoverview Implements Task WysiwygCommand - * @author NHN FE Development Lab - */ -var Task = _commandManager2.default.command('wysiwyg', /** @lends Task */{ - name: 'Task', - keyMap: ['ALT+T', 'ALT+T'], - /** - * Command Handler - * @param {WysiwygEditor} wwe WYSIWYGEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var range = sq.getSelection(); - var listManager = wwe.componentManager.getManager('list'); - var startContainer = range.startContainer, - endContainer = range.endContainer, - startOffset = range.startOffset, - endOffset = range.endOffset; - - var newLIs = []; - - wwe.focus(); - - sq.saveUndoState(range); - - if (listManager.isAvailableMakeListInTable()) { - newLIs = listManager.createListInTable(range, 'TASK'); - } else { - var lines = listManager.getLinesOfSelection(startContainer, endContainer); - - for (var i = 0; i < lines.length; i += 1) { - var newLI = this._changeFormatToTaskIfNeed(wwe, lines[i]); - if (newLI) { - newLIs.push(newLI); - } - } - } - - if (newLIs.length) { - listManager.adjustRange(startContainer, endContainer, startOffset, endOffset, newLIs); - } - }, - - - /** - * Change format to unordered list and return current li element if need - * @param {WysiwygEditor} wwe Wysiwyg editor instance - * @param {HTMLElement} target Element target for change - * @returns {HTMLElement} newly created list - * @private - */ - _changeFormatToTaskIfNeed: function _changeFormatToTaskIfNeed(wwe, target) { - var sq = wwe.getEditor(); - var range = sq.getSelection(); - var taskManager = wwe.componentManager.getManager('task'); - var newLI = void 0; - - if (!sq.hasFormat('PRE')) { - range.setStart(target, 0); - range.collapse(true); - sq.setSelection(range); - - if (!sq.hasFormat('li')) { - sq.makeUnorderedList(); - target = sq.getSelection().startContainer; - } - - if ((0, _jquery2.default)(target).hasClass('task-list-item')) { - taskManager.unformatTask(target); - } else { - taskManager.formatTask(target); - } - - newLI = sq.getSelection().startContainer; - } - - return newLI; - } -}); - -exports.default = Task; - -/***/ }), -/* 152 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -var _domUtils = __webpack_require__(4); - -var _domUtils2 = _interopRequireDefault(_domUtils); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Code - * Add bold to selected wysiwyg editor content - * @extends Command - * @module wysiwygCommands/Code - * @ignore - */ -/** - * @fileoverview Implements code WysiwygCommand - * @author NHN FE Development Lab - */ -var Code = _commandManager2.default.command('wysiwyg', /** @lends Code */{ - name: 'Code', - keyMap: ['SHIFT+CTRL+C', 'SHIFT+META+C'], - /** - * command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - */ - exec: function exec(wwe) { - var sq = wwe.getEditor(); - var tableSelectionManager = wwe.componentManager.getManager('tableSelection'); - var _styleCode = _tuiCodeSnippet2.default.bind(styleCode, null, wwe.getEditor()); - - wwe.focus(); - - if (sq.hasFormat('table') && tableSelectionManager.getSelectedCells().length) { - tableSelectionManager.styleToSelectedCells(_styleCode); - - var range = sq.getSelection(); - range.collapse(true); - sq.setSelection(range); - } else { - _styleCode(sq); - } - } -}); - -/** - * removeUnnecessaryCodeInNextToRange - * Remove unnecessary code tag next to range, code tag made by squire - * @param {Range} range range object - */ -function removeUnnecessaryCodeInNextToRange(range) { - if (_domUtils2.default.getNodeName(range.startContainer.nextSibling) === 'CODE' && _domUtils2.default.getTextLength(range.startContainer.nextSibling) === 0) { - (0, _jquery2.default)(range.startContainer.nextSibling).remove(); - } -} - -/** - * Style code. - * @param {object} editor - editor instance - * @param {object} sq - squire editor instance - */ -function styleCode(editor, sq) { - if (!sq.hasFormat('PRE') && sq.hasFormat('code')) { - sq.changeFormat(null, { tag: 'code' }); - removeUnnecessaryCodeInNextToRange(editor.getSelection().cloneRange()); - } else if (!sq.hasFormat('a') && !sq.hasFormat('PRE')) { - if (sq.hasFormat('b')) { - sq.removeBold(); - } else if (sq.hasFormat('i')) { - sq.removeItalic(); - } - - sq.changeFormat({ tag: 'code' }); - - var range = sq.getSelection().cloneRange(); - range.setStart(range.endContainer, range.endOffset); - range.collapse(true); - - sq.setSelection(range); - } -} - -exports.default = Code; - -/***/ }), -/* 153 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _jquery = __webpack_require__(0); - -var _jquery2 = _interopRequireDefault(_jquery); - -var _tuiCodeSnippet = __webpack_require__(1); - -var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); - -var _commandManager = __webpack_require__(2); - -var _commandManager2 = _interopRequireDefault(_commandManager); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var CODEBLOCK_CLASS_TEMP = 'te-content-codeblock-temp'; /** - * @fileoverview Implements code block WysiwygCommand - * @author NHN FE Development Lab - */ - -var CODEBLOCK_ATTR_NAME = 'data-te-codeblock'; - -/** - * CodeBlock - * Add CodeBlock to wysiwygEditor - * @extends Command - * @module wysiwygCommands/Codeblock - * @ignore - */ -var CodeBlock = _commandManager2.default.command('wysiwyg', /** @lends CodeBlock */{ - name: 'CodeBlock', - keyMap: ['SHIFT+CTRL+P', 'SHIFT+META+P'], - /** - * Command handler - * @param {WysiwygEditor} wwe wysiwygEditor instance - * @param {string} type of language - */ - exec: function exec(wwe, type) { - var sq = wwe.getEditor(); - var range = sq.getSelection().cloneRange(); - if (!sq.hasFormat('PRE') && !sq.hasFormat('TABLE')) { - var attr = CODEBLOCK_ATTR_NAME + ' class = "' + CODEBLOCK_CLASS_TEMP + '"'; - - if (type) { - attr += ' data-language="' + type + '"'; - } - - var codeBlockBody = getCodeBlockBody(range, wwe); - sq.insertHTML('
    ' + codeBlockBody + '
    '); - - focusToFirstCode(wwe.get$Body().find('.' + CODEBLOCK_CLASS_TEMP), wwe); - } - - wwe.focus(); - } -}); - -/** - * focusToFirstCode - * Focus to first code tag content of pre tag - * @param {jQuery} $pre pre tag - * @param {WysiwygEditor} wwe wysiwygEditor - */ -function focusToFirstCode($pre, wwe) { - var range = wwe.getEditor().getSelection().cloneRange(); - $pre.removeClass(CODEBLOCK_CLASS_TEMP); - - range.setStartBefore($pre.get(0).firstChild); - range.collapse(true); - - wwe.getEditor().setSelection(range); -} -/** - * getCodeBlockBody - * get text wrapped by code - * @param {object} range range object - * @param {object} wwe wysiwyg editor - * @returns {string} - */ -function getCodeBlockBody(range, wwe) { - var mgr = wwe.componentManager.getManager('codeblock'); - var codeBlock = void 0; - if (range.collapsed) { - codeBlock = '
    '; - } else { - var contents = range.extractContents(); - var nodes = _tuiCodeSnippet2.default.toArray(contents.childNodes); - var tempDiv = (0, _jquery2.default)('
    ').append(mgr.prepareToPasteOnCodeblock(nodes)); - codeBlock = tempDiv.html(); - } - - return codeBlock; -} - -exports.default = CodeBlock; - -/***/ }), -/* 154 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['en', 'en_US'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Write', - 'Preview': 'Preview', - 'Headings': 'Headings', - 'Paragraph': 'Paragraph', - 'Bold': 'Bold', - 'Italic': 'Italic', - 'Strike': 'Strike', - 'Code': 'Inline code', - 'Line': 'Line', - 'Blockquote': 'Blockquote', - 'Unordered list': 'Unordered list', - 'Ordered list': 'Ordered list', - 'Task': 'Task', - 'Indent': 'Indent', - 'Outdent': 'Outdent', - 'Insert link': 'Insert link', - 'Insert CodeBlock': 'Insert codeBlock', - 'Insert table': 'Insert table', - 'Insert image': 'Insert image', - 'Heading': 'Heading', - 'Image URL': 'Image URL', - 'Select image file': 'Select image file', - 'Description': 'Description', - 'OK': 'OK', - 'More': 'More', - 'Cancel': 'Cancel', - 'File': 'File', - 'URL': 'URL', - 'Link text': 'Link text', - 'Add row': 'Add row', - 'Add col': 'Add col', - 'Remove row': 'Remove row', - 'Remove col': 'Remove col', - 'Align left': 'Align left', - 'Align center': 'Align center', - 'Align right': 'Align right', - 'Remove table': 'Remove table', - 'Would you like to paste as table?': 'Would you like to paste as table?', - 'Text color': 'Text color', - 'Auto scroll enabled': 'Auto scroll enabled', - 'Auto scroll disabled': 'Auto scroll disabled', - 'Choose language': 'Choose language' -}); /** - * @fileoverview I18N for English - * @author NHN FE Development Lab - */ - -/***/ }), -/* 155 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['ko', 'ko_KR'], { - 'Markdown': '마크다운', - 'WYSIWYG': '위지윅', - 'Write': '편집하기', - 'Preview': '미리보기', - 'Headings': '제목크기', - 'Paragraph': '본문', - 'Bold': '굵게', - 'Italic': '기울임꼴', - 'Strike': '취소선', - 'Code': '인라인 코드', - 'Line': '문단나눔', - 'Blockquote': '인용구', - 'Unordered list': '글머리 기호', - 'Ordered list': '번호 매기기', - 'Task': '체크박스', - 'Indent': '들여쓰기', - 'Outdent': '내어쓰기', - 'Insert link': '링크 삽입', - 'Insert CodeBlock': '코드블럭 삽입', - 'Insert table': '표 삽입', - 'Insert image': '이미지 삽입', - 'Heading': '제목', - 'Image URL': '이미지 주소', - 'Select image file': '이미지 파일을 선택하세요.', - 'Description': '설명', - 'OK': '확인', - 'More': '더 보기', - 'Cancel': '취소', - 'File': '파일', - 'URL': '주소', - 'Link text': '링크 텍스트', - 'Add row': '행 추가', - 'Add col': '열 추가', - 'Remove row': '행 삭제', - 'Remove col': '열 삭제', - 'Align left': '왼쪽 정렬', - 'Align center': '가운데 정렬', - 'Align right': '오른쪽 정렬', - 'Remove table': '표 삭제', - 'Would you like to paste as table?': '표형태로 붙여 넣겠습니까?', - 'Text color': '글자 색상', - 'Auto scroll enabled': '자동 스크롤 켜짐', - 'Auto scroll disabled': '자동 스크롤 꺼짐', - 'Choose language': '언어 선택' -}); /** - * @fileoverview I18N for Korean - * @author NHN FE Development Lab - */ - -/***/ }), -/* 156 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['zh', 'zh_CN'], { - 'Markdown': 'Markdown', - 'WYSIWYG': '所见即所得', - 'Write': '编辑', - 'Preview': '预览', - 'Headings': '标题', - 'Paragraph': '文本', - 'Bold': '加粗', - 'Italic': '斜体字', - 'Strike': '删除线', - 'Code': '内嵌代码', - 'Line': '水平线', - 'Blockquote': '引用块', - 'Unordered list': '无序列表', - 'Ordered list': '有序列表', - 'Task': '任务', - 'Indent': '缩进', - 'Outdent': '减少缩进', - 'Insert link': '插入链接', - 'Insert CodeBlock': '插入代码块', - 'Insert table': '插入表格', - 'Insert image': '插入图片', - 'Heading': '标题', - 'Image URL': '图片网址', - 'Select image file': '选择图片文件', - 'Description': '说明', - 'OK': '确认', - 'More': '更多', - 'Cancel': '取消', - 'File': '文件', - 'URL': 'URL', - 'Link text': '链接文本', - 'Add row': '添加行', - 'Add col': '添加列', - 'Remove row': '删除行', - 'Remove col': '删除列', - 'Align left': '左对齐', - 'Align center': '居中对齐', - 'Align right': '右对齐', - 'Remove table': '删除表格', - 'Would you like to paste as table?': '需要粘贴为表格吗?', - 'Text color': '文字颜色', - 'Auto scroll enabled': '自动滚动已启用', - 'Auto scroll disabled': '自动滚动已禁用', - 'Choose language': '选择语言' -}); /** - * @fileoverview I18N for Chinese - * @author NHN FE Development Lab - */ - -/***/ }), -/* 157 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['ja', 'ja_JP'], { - 'Markdown': 'マークダウン', - 'WYSIWYG': 'WYSIWYG', - 'Write': '編集する', - 'Preview': 'プレビュー', - 'Headings': '見出し', - 'Paragraph': '本文', - 'Bold': '太字', - 'Italic': 'イタリック', - 'Strike': 'ストライク', - 'Code': 'インラインコード', - 'Line': 'ライン', - 'Blockquote': '引用', - 'Unordered list': '番号なしリスト', - 'Ordered list': '順序付きリスト', - 'Task': 'タスク', - 'Indent': 'インデント', - 'Outdent': 'アウトデント', - 'Insert link': 'リンク挿入', - 'Insert CodeBlock': 'コードブロック挿入', - 'Insert table': 'テーブル挿入', - 'Insert image': '画像挿入', - 'Heading': '見出し', - 'Image URL': 'イメージURL', - 'Select image file': '画像ファイル選択', - 'Description': 'ディスクリプション ', - 'OK': 'はい', - 'More': 'もっと', - 'Cancel': 'キャンセル', - 'File': 'ファイル', - 'URL': 'URL', - 'Link text': 'リンクテキスト', - 'Add row': '行追加', - 'Add col': '列追加', - 'Remove row': '行削除', - 'Remove col': '列削除', - 'Align left': '左揃え', - 'Align center': '中央揃え', - 'Align right': '右揃え', - 'Remove table': 'テーブル削除', - 'Would you like to paste as table?': 'テーブルを貼り付けますか?', - 'Text color': '文字色相', - 'Auto scroll enabled': '自動スクロールが有効', - 'Auto scroll disabled': '自動スクロールを無効に', - 'Choose language': '言語選択' -}); /** - * @fileoverview I18N for Japanese - * @author NHN FE Development Lab - */ - -/***/ }), -/* 158 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['nl', 'nl_NL'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Opslaan', - 'Preview': 'Voorbeeld', - 'Headings': 'Koppen', - 'Paragraph': 'Alinea', - 'Bold': 'Vet', - 'Italic': 'Cursief', - 'Strike': 'Doorhalen', - 'Code': 'Inline code', - 'Line': 'Regel', - 'Blockquote': 'Citaatblok', - 'Unordered list': 'Opsomming', - 'Ordered list': 'Genummerde opsomming', - 'Task': 'Taak', - 'Indent': 'Niveau verhogen', - 'Outdent': 'Niveau verlagen', - 'Insert link': 'Link invoegen', - 'Insert CodeBlock': 'Codeblok toevoegen', - 'Insert table': 'Tabel invoegen', - 'Insert image': 'Afbeelding invoegen', - 'Heading': 'Kop', - 'Image URL': 'Afbeelding URL', - 'Select image file': 'Selecteer een afbeelding', - 'Description': 'Omschrijving', - 'OK': 'OK', - 'More': 'Meer', - 'Cancel': 'Annuleren', - 'File': 'Bestand', - 'URL': 'URL', - 'Link text': 'Link tekst', - 'Add row': 'Rij toevoegen', - 'Add col': 'Kolom toevoegen', - 'Remove row': 'Rij verwijderen', - 'Remove col': 'Kolom verwijderen', - 'Align left': 'Links uitlijnen', - 'Align center': 'Centreren', - 'Align right': 'Rechts uitlijnen', - 'Remove table': 'Verwijder tabel', - 'Would you like to paste as table?': 'Wil je dit als tabel plakken?', - 'Text color': 'Tekstkleur', - 'Auto scroll enabled': 'Autoscroll ingeschakeld', - 'Auto scroll disabled': 'Autoscroll uitgeschakeld', - 'Choose language': 'Kies een taal' -}); /** - * @fileoverview I18N for Dutch - * @author NHN FE Development Lab - */ - -/***/ }), -/* 159 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['es', 'es_ES'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Escribir', - 'Preview': 'Vista previa', - 'Headings': 'Encabezados', - 'Paragraph': 'Párrafo', - 'Bold': 'Negrita', - 'Italic': 'Itálica', - 'Strike': 'Tachado', - 'Code': 'Código', - 'Line': 'Línea', - 'Blockquote': 'Cita', - 'Unordered list': 'Lista desordenada', - 'Ordered list': 'Lista ordenada', - 'Task': 'Tarea', - 'Indent': 'Sangría', - 'Outdent': 'Saliendo', - 'Insert link': 'Insertar enlace', - 'Insert CodeBlock': 'Insertar bloque de código', - 'Insert table': 'Insertar tabla', - 'Insert image': 'Insertar imagen', - 'Heading': 'Encabezado', - 'Image URL': 'URL de la imagen', - 'Select image file': 'Seleccionar archivo de imagen', - 'Description': 'Descripción', - 'OK': 'Aceptar', - 'More': 'Más', - 'Cancel': 'Cancelar', - 'File': 'Archivo', - 'URL': 'URL', - 'Link text': 'Texto del enlace', - 'Add row': 'Agregar fila', - 'Add col': 'Agregar columna', - 'Remove row': 'Eliminar fila', - 'Remove col': 'Eliminar columna', - 'Align left': 'Alinear a la izquierda', - 'Align center': 'Centrar', - 'Align right': 'Alinear a la derecha', - 'Remove table': 'Eliminar tabla', - 'Would you like to paste as table?': '¿Desea pegar como tabla?', - 'Text color': 'Color del texto', - 'Auto scroll enabled': 'Desplazamiento automático habilitado', - 'Auto scroll disabled': 'Desplazamiento automático deshabilitado', - 'Choose language': 'Elegir idioma' -}); /** - * @fileoverview I18N for Spanish - * @author Enrico Lamperti - */ - -/***/ }), -/* 160 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['de', 'de_DE'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Verfassen', - 'Preview': 'Vorschau', - 'Headings': 'Überschriften', - 'Paragraph': 'Text', - 'Bold': 'Fett', - 'Italic': 'Kursiv', - 'Strike': 'Durchgestrichen', - 'Code': 'Code', - 'Line': 'Trennlinie', - 'Blockquote': 'Blocktext', - 'Unordered list': 'Aufzählung', - 'Ordered list': 'Nummerierte Aufzählung', - 'Task': 'Aufgabe', - 'Indent': 'Einrücken', - 'Outdent': 'Ausrücken', - 'Insert link': 'Link einfügen', - 'Insert CodeBlock': 'Codeblock einfügen', - 'Insert table': 'Tabelle einfügen', - 'Insert image': 'Grafik einfügen', - 'Heading': 'Titel', - 'Image URL': 'Bild URL', - 'Select image file': 'Grafik auswählen', - 'Description': 'Beschreibung', - 'OK': 'OK', - 'More': 'Mehr', - 'Cancel': 'Abbrechen', - 'File': 'Datei', - 'URL': 'URL', - 'Link text': 'Anzuzeigender Text', - 'Add row': 'Zeile hinzufügen', - 'Add col': 'Spalte hinzufügen', - 'Remove row': 'Zeile entfernen', - 'Remove col': 'Spalte entfernen', - 'Align left': 'Links ausrichten', - 'Align center': 'Zentrieren', - 'Align right': 'Rechts ausrichten', - 'Remove table': 'Tabelle entfernen', - 'Would you like to paste as table?': 'Möchten Sie eine Tabelle einfügen?', - 'Text color': 'Textfarbe', - 'Auto scroll enabled': 'Autoscrollen aktiviert', - 'Auto scroll disabled': 'Autoscrollen deaktiviert', - 'Choose language': 'Sprache auswählen' -}); /** - * @fileoverview I18N for German - * @author Jann-Niklas Kiepert - */ - -/***/ }), -/* 161 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['ru', 'ru_RU'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Написать', - 'Preview': 'Предварительный просмотр', - 'Headings': 'Заголовки', - 'Paragraph': 'Абзац', - 'Bold': 'Жирный', - 'Italic': 'Курсив', - 'Strike': 'Зачеркнутый', - 'Code': 'Встроенный код', - 'Line': 'Строка', - 'Blockquote': 'Блок цитирования', - 'Unordered list': 'Неупорядоченный список', - 'Ordered list': 'Упорядоченный список', - 'Task': 'Задача', - 'Indent': 'отступ', - 'Outdent': 'Выступ', - 'Insert link': 'Вставить ссылку', - 'Insert CodeBlock': 'Вставить код', - 'Insert table': 'Вставить таблицу', - 'Insert image': 'Вставить изображение', - 'Heading': 'Заголовок', - 'Image URL': 'URL изображения', - 'Select image file': 'Выбрать файл изображения', - 'Description': 'Описание', - 'OK': 'Хорошо', - 'More': 'еще', - 'Cancel': 'Отмена', - 'File': 'Файл', - 'URL': 'URL', - 'Link text': 'Текст ссылки', - 'Add row': 'Добавить ряд', - 'Add col': 'Добавить столбец', - 'Remove row': 'Удалить ряд', - 'Remove col': 'Удалить столбец', - 'Align left': 'Выровнять по левому краю', - 'Align center': 'Выровнять по центру', - 'Align right': 'Выровнять по правому краю', - 'Remove table': 'Удалить таблицу', - 'Would you like to paste as table?': 'Вы хотите вставить в виде таблицы?', - 'Text color': 'Цвет текста', - 'Auto scroll enabled': 'Автоматическая прокрутка включена', - 'Auto scroll disabled': 'Автоматическая прокрутка отключена', - 'Choose language': 'Выбрать язык' -}); /** - * @fileoverview I18N for Russian - * @author Stepan Samko - */ - -/***/ }), -/* 162 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['fr', 'fr_FR'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Écrire', - 'Preview': 'Aperçu', - 'Headings': 'En-têtes', - 'Paragraph': 'Paragraphe', - 'Bold': 'Gras', - 'Italic': 'Italique', - 'Strike': 'Barré', - 'Code': 'Code en ligne', - 'Line': 'Ligne', - 'Blockquote': 'Citation', - 'Unordered list': 'Liste non-ordonnée', - 'Ordered list': 'Liste ordonnée', - 'Task': 'Tâche', - 'Indent': 'Retrait', - 'Outdent': 'Sortir', - 'Insert link': 'Insérer un lien', - 'Insert CodeBlock': 'Insérer un bloc de code', - 'Insert table': 'Insérer un tableau', - 'Insert image': 'Insérer une image', - 'Heading': 'En-tête', - 'Image URL': 'URL de l\'image', - 'Select image file': 'Sélectionnez un fichier image', - 'Description': 'Description', - 'OK': 'OK', - 'More': 'de plus', - 'Cancel': 'Annuler', - 'File': 'Fichier', - 'URL': 'URL', - 'Link text': 'Texte du lien', - 'Add row': 'Ajouter une ligne', - 'Add col': 'Ajouter une colonne', - 'Remove row': 'Supprimer une ligne', - 'Remove col': 'Supprimer une colonne', - 'Align left': 'Aligner à gauche', - 'Align center': 'Aligner au centre', - 'Align right': 'Aligner à droite', - 'Remove table': 'Supprimer le tableau', - 'Would you like to paste as table?': 'Voulez-vous coller ce contenu en tant que tableau ?', - 'Text color': 'Couleur du texte', - 'Auto scroll enabled': 'Défilement automatique activé', - 'Auto scroll disabled': 'Défilement automatique désactivé', - 'Choose language': 'Choix de la langue' -}); /** - * @fileoverview I18N for French - * @author Stanislas Michalak - */ - -/***/ }), -/* 163 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['uk', 'uk_UA'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Написати', - 'Preview': 'Попередній перегляд', - 'Headings': 'Заголовки', - 'Paragraph': 'Абзац', - 'Bold': 'Жирний', - 'Italic': 'Курсив', - 'Strike': 'Закреслений', - 'Code': 'Вбудований код', - 'Line': 'Лінія', - 'Blockquote': 'Блок цитування', - 'Unordered list': 'Невпорядкований список', - 'Ordered list': 'Упорядкований список', - 'Task': 'Завдання', - 'Indent': 'відступ', - 'Outdent': 'застарілий', - 'Insert link': 'Вставити посилання', - 'Insert CodeBlock': 'Вставити код', - 'Insert table': 'Вставити таблицю', - 'Insert image': 'Вставити зображення', - 'Heading': 'Заголовок', - 'Image URL': 'URL зображення', - 'Select image file': 'Вибрати файл зображення', - 'Description': 'Опис', - 'OK': 'OK', - 'More': 'ще', - 'Cancel': 'Скасувати', - 'File': 'Файл', - 'URL': 'URL', - 'Link text': 'Текст посилання', - 'Add row': 'Додати ряд', - 'Add col': 'Додати стовпчик', - 'Remove row': 'Видалити ряд', - 'Remove col': 'Видалити стовпчик', - 'Align left': 'Вирівняти по лівому краю', - 'Align center': 'Вирівняти по центру', - 'Align right': 'Вирівняти по правому краю', - 'Remove table': 'Видалити таблицю', - 'Would you like to paste as table?': 'Ви хочете вставити у вигляді таблиці?', - 'Text color': 'Колір тексту', - 'Auto scroll enabled': 'Автоматична прокрутка включена', - 'Auto scroll disabled': 'Автоматична прокрутка відключена', - 'Choose language': 'Вибрати мову' -}); /** - * @fileoverview I18N for Ukrainian - * @author Nikolya - */ - -/***/ }), -/* 164 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['tr', 'tr_TR'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Düzenle', - 'Preview': 'Ön izleme', - 'Headings': 'Başlıklar', - 'Paragraph': 'Paragraf', - 'Bold': 'Kalın', - 'Italic': 'İtalik', - 'Strike': 'Altı çizgili', - 'Code': 'Satır içi kod', - 'Line': 'Çizgi', - 'Blockquote': 'Alıntı', - 'Unordered list': 'Sıralanmamış liste', - 'Ordered list': 'Sıralı liste', - 'Task': 'Görev kutusu', - 'Indent': 'Girintiyi arttır', - 'Outdent': 'Girintiyi azalt', - 'Insert link': 'Bağlantı ekle', - 'Insert CodeBlock': 'Kod bloku ekle', - 'Insert table': 'Tablo ekle', - 'Insert image': 'İmaj ekle', - 'Heading': 'Başlık', - 'Image URL': 'İmaj URL', - 'Select image file': 'İmaj dosyası seç', - 'Description': 'Açıklama', - 'OK': 'Onay', - 'More': 'Daha Fazla', - 'Cancel': 'İptal', - 'File': 'Dosya', - 'URL': 'URL', - 'Link text': 'Bağlantı yazısı', - 'Add row': 'Satır ekle', - 'Add col': 'Sütun ekle', - 'Remove row': 'Satır sil', - 'Remove col': 'Sütun sil', - 'Align left': 'Sola hizala', - 'Align center': 'Merkeze hizala', - 'Align right': 'Sağa hizala', - 'Remove table': 'Tabloyu kaldır', - 'Would you like to paste as table?': 'Tablo olarak yapıştırmak ister misiniz?', - 'Text color': 'Metin rengi', - 'Auto scroll enabled': 'Otomatik kaydırma açık', - 'Auto scroll disabled': 'Otomatik kaydırma kapalı', - 'Choose language': 'Dil seçiniz' -}); /** - * @fileoverview I18N for Turkish - * @author Mesut Gölcük - */ - -/***/ }), -/* 165 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['fi', 'fi_FI'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Kirjoita', - 'Preview': 'Esikatselu', - 'Headings': 'Otsikot', - 'Paragraph': 'Kappale', - 'Bold': 'Lihavointi', - 'Italic': 'Kursivointi', - 'Strike': 'Yliviivaus', - 'Code': 'Koodi', - 'Line': 'Vaakaviiva', - 'Blockquote': 'Lainaus', - 'Unordered list': 'Luettelo', - 'Ordered list': 'Numeroitu luettelo', - 'Task': 'Tehtävä', - 'Indent': 'Suurenna sisennystä', - 'Outdent': 'Pienennä sisennystä', - 'Insert link': 'Lisää linkki', - 'Insert CodeBlock': 'Lisää koodia', - 'Insert table': 'Lisää taulukko', - 'Insert image': 'Lisää kuva', - 'Heading': 'Otsikko', - 'Image URL': 'Kuvan URL', - 'Select image file': 'Valitse kuvatiedosto', - 'Description': 'Kuvaus', - 'OK': 'OK', - 'More': 'Lisää', - 'Cancel': 'Peruuta', - 'File': 'Tiedosto', - 'URL': 'URL', - 'Link text': 'Linkkiteksti', - 'Add row': 'Lisää rivi', - 'Add col': 'Lisää sarake', - 'Remove row': 'Poista rivi', - 'Remove col': 'Poista sarake', - 'Align left': 'Tasaus vasemmalle', - 'Align center': 'Keskitä', - 'Align right': 'Tasaus oikealle', - 'Remove table': 'Poista taulukko', - 'Would you like to paste as table?': 'Haluatko liittää taulukkomuodossa?', - 'Text color': 'Tekstin väri', - 'Auto scroll enabled': 'Automaattinen skrollaus käytössä', - 'Auto scroll disabled': 'Automaattinen skrollaus pois käytöstä', - 'Choose language': 'Valitse kieli' -}); /** - * @fileoverview I18N for Finnish - * @author Tomi Mynttinen - */ - -/***/ }), -/* 166 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['cs', 'cs_CZ'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Napsat', - 'Preview': 'Náhled', - 'Headings': 'Nadpisy', - 'Paragraph': 'Odstavec', - 'Bold': 'Tučné', - 'Italic': 'Kurzíva', - 'Strike': 'Přeškrtnuté', - 'Code': 'Kód', - 'Line': 'Vodorovná čára', - 'Blockquote': 'Citace', - 'Unordered list': 'Seznam s odrážkami', - 'Ordered list': 'Číslovaný seznam', - 'Task': 'Úkol', - 'Indent': 'Zvětšit odsazení', - 'Outdent': 'Zmenšit odsazení', - 'Insert link': 'Vložit odkaz', - 'Insert CodeBlock': 'Vložit blok kódu', - 'Insert table': 'Vložit tabulku', - 'Insert image': 'Vložit obrázek', - 'Heading': 'Nadpis', - 'Image URL': 'URL obrázku', - 'Select image file': 'Vybrat obrázek', - 'Description': 'Popis', - 'OK': 'OK', - 'More': 'Více', - 'Cancel': 'Zrušit', - 'File': 'Soubor', - 'URL': 'URL', - 'Link text': 'Text odkazu', - 'Add row': 'Přidat řádek', - 'Add col': 'Přidat sloupec', - 'Remove row': 'Odebrat řádek', - 'Remove col': 'Odebrat sloupec', - 'Align left': 'Zarovnat vlevo', - 'Align center': 'Zarovnat na střed', - 'Align right': 'Zarovnat vpravo', - 'Remove table': 'Odstranit tabulku', - 'Would you like to paste as table?': 'Chcete vložit jako tabulku?', - 'Text color': 'Barva textu', - 'Auto scroll enabled': 'Automatické rolování zapnuto', - 'Auto scroll disabled': 'Automatické rolování vypnuto', - 'Choose language': 'Vybrat jazyk' -}); /** - * @fileoverview I18N for Czech - * @author Dmitrij Tkačenko - */ - -/***/ }), -/* 167 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['ar', 'ar_AR'], { - 'Markdown': 'لغة ترميز', - 'WYSIWYG': 'ما تراه هو ما تحصل عليه', - 'Write': 'يكتب', - 'Preview': 'عرض مسبق', - 'Headings': 'العناوين', - 'Paragraph': 'فقرة', - 'Bold': 'خط عريض', - 'Italic': 'خط مائل', - 'Strike': 'إضراب', - 'Code': 'رمز', - 'Line': 'خط', - 'Blockquote': 'فقرة مقتبسة', - 'Unordered list': 'قائمة غير مرتبة', - 'Ordered list': 'قائمة مرتبة', - 'Task': 'مهمة', - 'Indent': 'المسافة البادئة', - 'Outdent': 'المسافة الخارجة', - 'Insert link': 'أدخل الرابط', - 'Insert CodeBlock': 'أدخل الكود', - 'Insert table': 'أدخل جدول', - 'Insert image': 'أدخل صورة', - 'Heading': 'عنوان', - 'Image URL': 'رابط الصورة', - 'Select image file': 'حدد ملف الصورة', - 'Description': 'وصف', - 'OK': 'موافقة', - 'More': 'أكثر', - 'Cancel': 'إلغاء', - 'File': 'ملف', - 'URL': 'رابط', - 'Link text': 'نص الرابط', - 'Add row': 'ضف سطر', - 'Add col': 'ضف عمود', - 'Remove row': 'حذف سطر', - 'Remove col': 'حذف عمود', - 'Align left': 'محاذاة اليسار', - 'Align center': 'محاذاة الوسط', - 'Align right': 'محاذاة اليمين', - 'Remove table': 'حذف الجدول', - 'Would you like to paste as table?': 'هل تريد اللصق كجدول', - 'Text color': 'لون النص', - 'Auto scroll enabled': 'التحريك التلقائي ممكّن', - 'Auto scroll disabled': 'التحريك التلقائي معطّل', - 'Choose language': 'اختر اللغة' -}); /** - * @fileoverview I18N for Arabic - * @author Amira Salah - */ - -/***/ }), -/* 168 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['pl', 'pl_PL'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Napisz', - 'Preview': 'Podgląd', - 'Headings': 'Nagłówki', - 'Paragraph': 'Akapit', - 'Bold': 'Pogrubienie', - 'Italic': 'Kursywa', - 'Strike': 'Przekreślenie', - 'Code': 'Fragment kodu', - 'Line': 'Linia', - 'Blockquote': 'Cytat', - 'Unordered list': 'Lista nieuporządkowana', - 'Ordered list': 'Lista uporządkowana', - 'Task': 'Zadanie', - 'Indent': 'Utwórz wcięcie', - 'Outdent': 'Usuń wcięcie', - 'Insert link': 'Umieść odnośnik', - 'Insert CodeBlock': 'Umieść blok kodu', - 'Insert table': 'Umieść tabelę', - 'Insert image': 'Umieść obraz', - 'Heading': 'Nagłówek', - 'Image URL': 'Adres URL obrazu', - 'Select image file': 'Wybierz plik obrazu', - 'Description': 'Opis', - 'OK': 'OK', - 'More': 'Więcej', - 'Cancel': 'Anuluj', - 'File': 'Plik', - 'URL': 'URL', - 'Link text': 'Tekst odnośnika', - 'Add row': 'Dodaj rząd', - 'Add col': 'Dodaj kolumnę', - 'Remove row': 'Usuń rząd', - 'Remove col': 'Usuń kolumnę', - 'Align left': 'Wyrównaj do lewej', - 'Align center': 'Wyśrodkuj', - 'Align right': 'Wyrównaj do prawej', - 'Remove table': 'Usuń tabelę', - 'Would you like to paste as table?': 'Czy chcesz wkleić tekst jako tabelę?', - 'Text color': 'Kolor tekstu', - 'Auto scroll enabled': 'Włączono automatyczne przewijanie', - 'Auto scroll disabled': 'Wyłączono automatyczne przewijanie', - 'Choose language': 'Wybierz język' -}); /** - * @fileoverview I18N for Polish - * @author Marcin Mikołajczak - */ - -/***/ }), -/* 169 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['zhtw', 'zh_TW'], { - 'Markdown': 'Markdown', - 'WYSIWYG': '所見即所得', - 'Write': '編輯', - 'Preview': '預覽', - 'Headings': '標題', - 'Paragraph': '內文', - 'Bold': '粗體', - 'Italic': '斜體', - 'Strike': '刪除線', - 'Code': '內嵌程式碼', - 'Line': '分隔線', - 'Blockquote': '引言', - 'Unordered list': '項目符號清單', - 'Ordered list': '編號清單', - 'Task': '核取方塊清單', - 'Indent': '增加縮排', - 'Outdent': '減少縮排', - 'Insert link': '插入超連結', - 'Insert CodeBlock': '插入程式碼區塊', - 'Insert table': '插入表格', - 'Insert image': '插入圖片', - 'Heading': '標題', - 'Image URL': '圖片網址', - 'Select image file': '選擇圖片檔案', - 'Description': '描述', - 'OK': '確認', - 'More': '更多', - 'Cancel': '取消', - 'File': '檔案', - 'URL': 'URL', - 'Link text': '超連結文字', - 'Add row': '增加行', - 'Add col': '增加列', - 'Remove row': '刪除行', - 'Remove col': '刪除列', - 'Align left': '靠左對齊', - 'Align center': '置中', - 'Align right': '靠右對齊', - 'Remove table': '刪除表格', - 'Would you like to paste as table?': '您要以表格貼上嗎?', - 'Text color': '文字顏色', - 'Auto scroll enabled': '已啟用自動滾動', - 'Auto scroll disabled': '已停用自動滾動', - 'Choose language': '選擇語言' -}); /** - * @fileoverview I18N for Traditional Chinese - * @author Tzu-Ray Su - */ - -/***/ }), -/* 170 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['gl', 'gl_ES'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Escribir', - 'Preview': 'Vista previa', - 'Headings': 'Encabezados', - 'Paragraph': 'Parágrafo', - 'Bold': 'Negriña', - 'Italic': 'Cursiva', - 'Strike': 'Riscado', - 'Code': 'Código', - 'Line': 'Liña', - 'Blockquote': 'Cita', - 'Unordered list': 'Lista desordenada', - 'Ordered list': 'Lista ordenada', - 'Task': 'Tarefa', - 'Indent': 'Sangría', - 'Outdent': 'Anular sangría', - 'Insert link': 'Inserir enlace', - 'Insert CodeBlock': 'Inserir bloque de código', - 'Insert table': 'Inserir táboa', - 'Insert image': 'Inserir imaxe', - 'Heading': 'Encabezado', - 'Image URL': 'URL da imaxe', - 'Select image file': 'Seleccionar arquivo da imaxe', - 'Description': 'Descrición', - 'OK': 'Aceptar', - 'More': 'Máis', - 'Cancel': 'Cancelar', - 'File': 'Arquivo', - 'URL': 'URL', - 'Link text': 'Texto do enlace', - 'Add row': 'Agregar fila', - 'Add col': 'Agregar columna', - 'Remove row': 'Eliminar fila', - 'Remove col': 'Eliminar columna', - 'Align left': 'Aliñar á esquerda', - 'Align center': 'Centrar', - 'Align right': 'Aliñar á dereita', - 'Remove table': 'Eliminar táboa', - 'Would you like to paste as table?': 'Desexa pegar como táboa?', - 'Text color': 'Cor do texto', - 'Auto scroll enabled': 'Desprazamento automático habilitado', - 'Auto scroll disabled': 'Desprazamento automático deshabilitado', - 'Choose language': 'Elixir idioma' -}); /** - * @fileoverview I18N for Spanish - * @author Aida Vidal - */ - -/***/ }), -/* 171 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['sv', 'sv_SE'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Skriv', - 'Preview': 'Förhandsgranska', - 'Headings': 'Överskrifter', - 'Paragraph': 'Paragraf', - 'Bold': 'Fet', - 'Italic': 'Kursiv', - 'Strike': 'Genomstruken', - 'Code': 'Kodrad', - 'Line': 'Linje', - 'Blockquote': 'Citatblock', - 'Unordered list': 'Punktlista', - 'Ordered list': 'Numrerad lista', - 'Task': 'Att göra', - 'Indent': 'Öka indrag', - 'Outdent': 'Minska indrag', - 'Insert link': 'Infoga länk', - 'Insert CodeBlock': 'Infoga kodblock', - 'Insert table': 'Infoga tabell', - 'Insert image': 'Infoga bild', - 'Heading': 'Överskrift', - 'Image URL': 'Bildadress', - 'Select image file': 'Välj en bildfil', - 'Description': 'Beskrivning', - 'OK': 'OK', - 'More': 'Mer', - 'Cancel': 'Avbryt', - 'File': 'Fil', - 'URL': 'Adress', - 'Link text': 'Länktext', - 'Add row': 'Infoga rad', - 'Add col': 'Infoga kolumn', - 'Remove row': 'Radera rad', - 'Remove col': 'Radera kolumn', - 'Align left': 'Vänsterjustera', - 'Align center': 'Centrera', - 'Align right': 'Högerjustera', - 'Remove table': 'Radera tabell', - 'Would you like to paste as table?': 'Vill du klistra in som en tabell?', - 'Text color': 'Textfärg', - 'Auto scroll enabled': 'Automatisk scroll aktiverad', - 'Auto scroll disabled': 'Automatisk scroll inaktiverad', - 'Choose language': 'Välj språk' -}); /** - * @fileoverview I18N for Swedish - * @author Magnus Aspling - */ - -/***/ }), -/* 172 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _i18n = __webpack_require__(3); - -var _i18n2 = _interopRequireDefault(_i18n); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_i18n2.default.setLanguage(['it', 'it_IT'], { - 'Markdown': 'Markdown', - 'WYSIWYG': 'WYSIWYG', - 'Write': 'Scrivere', - 'Preview': 'Anteprima', - 'Headings': 'Intestazioni', - 'Paragraph': 'Paragrafo', - 'Bold': 'Grassetto', - 'Italic': 'Corsivo', - 'Strike': 'Barrato', - 'Code': 'Codice', - 'Line': 'Linea', - 'Blockquote': 'Blocco citazione', - 'Unordered list': 'Lista puntata', - 'Ordered list': 'Lista numerata', - 'Task': 'Attività', - 'Indent': 'Aggiungi indentazione', - 'Outdent': 'Rimuovi indentazione', - 'Insert link': 'Inserisci link', - 'Insert CodeBlock': 'Inserisci blocco di codice', - 'Insert table': 'Inserisci tabella', - 'Insert image': 'Inserisci immagine', - 'Heading': 'Intestazione', - 'Image URL': 'URL immagine', - 'Select image file': 'Seleziona file immagine', - 'Description': 'Descrizione', - 'OK': 'OK', - 'More': 'Più', - 'Cancel': 'Cancella', - 'File': 'File', - 'URL': 'URL', - 'Link text': 'Testo del collegamento', - 'Add row': 'Aggiungi riga', - 'Add col': 'Aggiungi colonna', - 'Remove row': 'Rimuovi riga', - 'Remove col': 'Rimuovi colonna', - 'Align left': 'Allinea a sinistra', - 'Align center': 'Allinea al centro', - 'Align right': 'Allinea a destra', - 'Remove table': 'Rimuovi tabella', - 'Would you like to paste as table?': 'Desideri incollare sotto forma di tabella?', - 'Text color': 'Colore del testo', - 'Auto scroll enabled': 'Scrolling automatico abilitato', - 'Auto scroll disabled': 'Scrolling automatico disabilitato', - 'Choose language': 'Scegli la lingua' -}); /** - * @fileoverview I18N for Italian - * @author Massimo Redaelli - */ - -/***/ }), -/* 173 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -/* eslint-disable */ -/* - CSV-JS - A Comma-Separated Values parser for JS - - Built to rfc4180 standard, with options for adjusting strictness: - - optional carriage returns for non-microsoft sources - - automatically type-cast numeric an boolean values - - relaxed mode which: ignores blank lines, ignores gargabe following quoted tokens, does not enforce a consistent record length - - Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - Author Greg Kindel (twitter @gkindel), 2014 - */ -/** - * @modifier NHN FE Development Lab - */ - -(function (global) { - 'use strict'; - /** - * @name CSV - * @namespace - * @ignore - */ - // implemented as a singleton because JS is single threaded - - var CSV = {}; - CSV.RELAXED = false; - CSV.IGNORE_RECORD_LENGTH = false; - CSV.IGNORE_QUOTES = false; - CSV.LINE_FEED_OK = true; - CSV.CARRIAGE_RETURN_OK = true; - CSV.DETECT_TYPES = true; - CSV.IGNORE_QUOTE_WHITESPACE = true; - CSV.DEBUG = false; - - CSV.COLUMN_SEPARATOR = ","; - - CSV.ERROR_EOF = "UNEXPECTED_END_OF_FILE"; - CSV.ERROR_CHAR = "UNEXPECTED_CHARACTER"; - CSV.ERROR_EOL = "UNEXPECTED_END_OF_RECORD"; - CSV.WARN_SPACE = "UNEXPECTED_WHITESPACE"; // not per spec, but helps debugging - - var QUOTE = "\"", - CR = "\r", - LF = "\n", - SPACE = " ", - TAB = "\t"; - - // states - var PRE_TOKEN = 0, - MID_TOKEN = 1, - POST_TOKEN = 2, - POST_RECORD = 4; - /** - * @name CSV.parse - * @function - * @description rfc4180 standard csv parse - * with options for strictness and data type conversion - * By default, will automatically type-cast numeric an boolean values. - * @param {String} str A CSV string - * @return {Array} An array records, each of which is an array of scalar values. - * @example - * // simple - * var rows = CSV.parse("one,two,three\nfour,five,six") - * // rows equals [["one","two","three"],["four","five","six"]] - * @example - * // Though not a jQuery plugin, it is recommended to use with the $.ajax pipe() method: - * $.get("csv.txt") - * .pipe( CSV.parse ) - * .done( function(rows) { - * for( var i =0; i < rows.length; i++){ - * console.log(rows[i]) - * } - * }); - * @see http://www.ietf.org/rfc/rfc4180.txt - */ - CSV.parse = function (str) { - var result = CSV.result = []; - CSV.COLUMN_SEPARATOR = CSV.COLUMN_SEPARATOR instanceof RegExp ? new RegExp('^' + CSV.COLUMN_SEPARATOR.source) : CSV.COLUMN_SEPARATOR; - - CSV.offset = 0; - CSV.str = str; - CSV.record_begin(); - - CSV.debug("parse()", str); - - var c; - while (1) { - // pull char - c = str[CSV.offset++]; - CSV.debug("c", c); - - // detect eof - if (c == null) { - if (CSV.escaped) { - CSV.error(CSV.ERROR_EOF); - } - - if (CSV.record) { - CSV.token_end(); - CSV.record_end(); - } - - CSV.debug("...bail", c, CSV.state, CSV.record); - CSV.reset(); - break; - } - - if (CSV.record == null) { - // if relaxed mode, ignore blank lines - if (CSV.RELAXED && (c == LF || c == CR && str[CSV.offset + 1] == LF)) { - continue; - } - CSV.record_begin(); - } - - // pre-token: look for start of escape sequence - if (CSV.state == PRE_TOKEN) { - - if ((c === SPACE || c === TAB) && CSV.next_nonspace() == QUOTE) { - if (CSV.RELAXED || CSV.IGNORE_QUOTE_WHITESPACE) { - continue; - } else { - // not technically an error, but ambiguous and hard to debug otherwise - CSV.warn(CSV.WARN_SPACE); - } - } - - if (c == QUOTE && !CSV.IGNORE_QUOTES) { - CSV.debug("...escaped start", c); - CSV.escaped = true; - CSV.state = MID_TOKEN; - continue; - } - CSV.state = MID_TOKEN; - } - - // mid-token and escaped, look for sequences and end quote - if (CSV.state == MID_TOKEN && CSV.escaped) { - if (c == QUOTE) { - if (str[CSV.offset] == QUOTE) { - CSV.debug("...escaped quote", c); - CSV.token += QUOTE; - CSV.offset++; - } else { - CSV.debug("...escaped end", c); - CSV.escaped = false; - CSV.state = POST_TOKEN; - } - } else { - CSV.token += c; - CSV.debug("...escaped add", c, CSV.token); - } - continue; - } - - // fall-through: mid-token or post-token, not escaped - if (c == CR) { - if (str[CSV.offset] == LF) CSV.offset++;else if (!CSV.CARRIAGE_RETURN_OK) CSV.error(CSV.ERROR_CHAR); - CSV.token_end(); - CSV.record_end(); - } else if (c == LF) { - if (!(CSV.LINE_FEED_OK || CSV.RELAXED)) CSV.error(CSV.ERROR_CHAR); - CSV.token_end(); - CSV.record_end(); - } else if (CSV.test_regex_separator(str) || CSV.COLUMN_SEPARATOR == c) { - CSV.token_end(); - } else if (CSV.state == MID_TOKEN) { - CSV.token += c; - CSV.debug("...add", c, CSV.token); - } else if (c === SPACE || c === TAB) { - if (!CSV.IGNORE_QUOTE_WHITESPACE) CSV.error(CSV.WARN_SPACE); - } else if (!CSV.RELAXED) { - CSV.error(CSV.ERROR_CHAR); - } - } - return result; - }; - - /** - * @name CSV.stream - * @function - * @description stream a CSV file - * @example - * node -e "c=require('CSV-JS');require('fs').createReadStream('csv.txt').pipe(c.stream()).pipe(c.stream.json()).pipe(process.stdout)" - * @ignore - */ - CSV.stream = function () { - var stream = __webpack_require__(47); - var s = new stream.Transform({ objectMode: true }); - s.EOL = '\n'; - s.prior = ""; - s.emitter = function (s) { - return function (e) { - s.push(CSV.parse(e + s.EOL)); - }; - }(s); - - s._transform = function (chunk, encoding, done) { - var lines = this.prior == "" ? chunk.toString().split(this.EOL) : (this.prior + chunk.toString()).split(this.EOL); - this.prior = lines.pop(); - lines.forEach(this.emitter); - done(); - }; - - s._flush = function (done) { - if (this.prior != "") { - this.emitter(this.prior); - this.prior = ""; - } - done(); - }; - return s; - }; - - CSV.test_regex_separator = function (str) { - if (!(CSV.COLUMN_SEPARATOR instanceof RegExp)) { - return false; - } - - var match; - str = str.slice(CSV.offset - 1); - match = CSV.COLUMN_SEPARATOR.exec(str); - if (match) { - CSV.offset += match[0].length - 1; - } - - return match !== null; - }; - - CSV.stream.json = function () { - var os = __webpack_require__(187); - var stream = __webpack_require__(47); - var s = new streamTransform({ objectMode: true }); - s._transform = function (chunk, encoding, done) { - s.push(JSON.stringify(chunk.toString()) + os.EOL); - done(); - }; - return s; - }; - - CSV.reset = function () { - CSV.state = null; - CSV.token = null; - CSV.escaped = null; - CSV.record = null; - CSV.offset = null; - CSV.result = null; - CSV.str = null; - }; - - CSV.next_nonspace = function () { - var i = CSV.offset; - var c; - while (i < CSV.str.length) { - c = CSV.str[i++]; - if (!(c == SPACE || c === TAB)) { - return c; - } - } - return null; - }; - - CSV.record_begin = function () { - CSV.escaped = false; - CSV.record = []; - CSV.token_begin(); - CSV.debug("record_begin"); - }; - - CSV.record_end = function () { - CSV.state = POST_RECORD; - if (!(CSV.IGNORE_RECORD_LENGTH || CSV.RELAXED) && CSV.result.length > 0 && CSV.record.length != CSV.result[0].length) { - CSV.error(CSV.ERROR_EOL); - } - CSV.result.push(CSV.record); - CSV.debug("record end", CSV.record); - CSV.record = null; - }; - - CSV.resolve_type = function (token) { - if (token.match(/^[-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/)) { - token = parseFloat(token); - } else if (token.match(/^(true|false)$/i)) { - token = Boolean(token.match(/true/i)); - } else if (token === "undefined") { - token = undefined; - } else if (token === "null") { - token = null; - } - return token; - }; - - CSV.token_begin = function () { - CSV.state = PRE_TOKEN; - // considered using array, but http://www.sitepen.com/blog/2008/05/09/string-performance-an-analysis/ - CSV.token = ""; - }; - - CSV.token_end = function () { - if (CSV.DETECT_TYPES) { - CSV.token = CSV.resolve_type(CSV.token); - } - CSV.record.push(CSV.token); - CSV.debug("token end", CSV.token); - CSV.token_begin(); - }; - - CSV.debug = function () { - if (CSV.DEBUG) console.log(arguments); - }; - - CSV.dump = function (msg) { - return [msg, "at char", CSV.offset, ":", CSV.str.substr(CSV.offset - 50, 50).replace(/\r/mg, "\\r").replace(/\n/mg, "\\n").replace(/\t/mg, "\\t")].join(" "); - }; - - CSV.error = function (err) { - var msg = CSV.dump(err); - CSV.reset(); - throw msg; - }; - - CSV.warn = function (err) { - if (!CSV.DEBUG) { - return; - } - - var msg = CSV.dump(err); - try { - console.warn(msg); - return; - } catch (e) {} - - try { - console.log(msg); - } catch (e) {} - }; - - // Node, PhantomJS, etc - // eg. var CSV = require("CSV"); CSV.parse(...); - if ( true && module.exports) { - module.exports = CSV; - } - - // CommonJS http://wiki.commonjs.org/wiki/Modules - // eg. var CSV = require("CSV").CSV; CSV.parse(...); - else if (true) { - exports.CSV = CSV; - } - - // AMD https://github.com/amdjs/amdjs-api/wiki/AMD - // eg. require(['./csv.js'], function (CSV) { CSV.parse(...); } ); - else {} -})(undefined); - -/***/ }), -/* 174 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -exports.byteLength = byteLength -exports.toByteArray = toByteArray -exports.fromByteArray = fromByteArray - -var lookup = [] -var revLookup = [] -var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array - -var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -for (var i = 0, len = code.length; i < len; ++i) { - lookup[i] = code[i] - revLookup[code.charCodeAt(i)] = i -} - -// Support decoding URL-safe base64 strings, as Node.js does. -// See: https://en.wikipedia.org/wiki/Base64#URL_applications -revLookup['-'.charCodeAt(0)] = 62 -revLookup['_'.charCodeAt(0)] = 63 - -function getLens (b64) { - var len = b64.length - - if (len % 4 > 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } - - // Trim off extra bytes after placeholder bytes are found - // See: https://github.com/beatgammit/base64-js/issues/42 - var validLen = b64.indexOf('=') - if (validLen === -1) validLen = len - - var placeHoldersLen = validLen === len - ? 0 - : 4 - (validLen % 4) - - return [validLen, placeHoldersLen] -} - -// base64 is 4/3 + up to two characters of the original data -function byteLength (b64) { - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen -} - -function _byteLength (b64, validLen, placeHoldersLen) { - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen -} - -function toByteArray (b64) { - var tmp - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] - - var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) - - var curByte = 0 - - // if there are placeholders, only get up to the last complete 4 chars - var len = placeHoldersLen > 0 - ? validLen - 4 - : validLen - - var i - for (i = 0; i < len; i += 4) { - tmp = - (revLookup[b64.charCodeAt(i)] << 18) | - (revLookup[b64.charCodeAt(i + 1)] << 12) | - (revLookup[b64.charCodeAt(i + 2)] << 6) | - revLookup[b64.charCodeAt(i + 3)] - arr[curByte++] = (tmp >> 16) & 0xFF - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } - - if (placeHoldersLen === 2) { - tmp = - (revLookup[b64.charCodeAt(i)] << 2) | - (revLookup[b64.charCodeAt(i + 1)] >> 4) - arr[curByte++] = tmp & 0xFF - } - - if (placeHoldersLen === 1) { - tmp = - (revLookup[b64.charCodeAt(i)] << 10) | - (revLookup[b64.charCodeAt(i + 1)] << 4) | - (revLookup[b64.charCodeAt(i + 2)] >> 2) - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } - - return arr -} - -function tripletToBase64 (num) { - return lookup[num >> 18 & 0x3F] + - lookup[num >> 12 & 0x3F] + - lookup[num >> 6 & 0x3F] + - lookup[num & 0x3F] -} - -function encodeChunk (uint8, start, end) { - var tmp - var output = [] - for (var i = start; i < end; i += 3) { - tmp = - ((uint8[i] << 16) & 0xFF0000) + - ((uint8[i + 1] << 8) & 0xFF00) + - (uint8[i + 2] & 0xFF) - output.push(tripletToBase64(tmp)) - } - return output.join('') -} - -function fromByteArray (uint8) { - var tmp - var len = uint8.length - var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes - var parts = [] - var maxChunkLength = 16383 // must be multiple of 3 - - // go through the array every three bytes, we'll deal with trailing stuff later - for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk( - uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) - )) - } - - // pad the end with zeros, but make sure to not forget the extra bytes - if (extraBytes === 1) { - tmp = uint8[len - 1] - parts.push( - lookup[tmp >> 2] + - lookup[(tmp << 4) & 0x3F] + - '==' - ) - } else if (extraBytes === 2) { - tmp = (uint8[len - 2] << 8) + uint8[len - 1] - parts.push( - lookup[tmp >> 10] + - lookup[(tmp >> 4) & 0x3F] + - lookup[(tmp << 2) & 0x3F] + - '=' - ) - } - - return parts.join('') -} - - -/***/ }), -/* 175 */ -/***/ (function(module, exports) { - -exports.read = function (buffer, offset, isLE, mLen, nBytes) { - var e, m - var eLen = (nBytes * 8) - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var nBits = -7 - var i = isLE ? (nBytes - 1) : 0 - var d = isLE ? -1 : 1 - var s = buffer[offset + i] - - i += d - - e = s & ((1 << (-nBits)) - 1) - s >>= (-nBits) - nBits += eLen - for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} - - m = e & ((1 << (-nBits)) - 1) - e >>= (-nBits) - nBits += mLen - for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} - - if (e === 0) { - e = 1 - eBias - } else if (e === eMax) { - return m ? NaN : ((s ? -1 : 1) * Infinity) - } else { - m = m + Math.pow(2, mLen) - e = e - eBias - } - return (s ? -1 : 1) * m * Math.pow(2, e - mLen) -} - -exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { - var e, m, c - var eLen = (nBytes * 8) - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) - var i = isLE ? 0 : (nBytes - 1) - var d = isLE ? 1 : -1 - var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 - - value = Math.abs(value) - - if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0 - e = eMax - } else { - e = Math.floor(Math.log(value) / Math.LN2) - if (value * (c = Math.pow(2, -e)) < 1) { - e-- - c *= 2 - } - if (e + eBias >= 1) { - value += rt / c - } else { - value += rt * Math.pow(2, 1 - eBias) - } - if (value * c >= 2) { - e++ - c /= 2 - } - - if (e + eBias >= eMax) { - m = 0 - e = eMax - } else if (e + eBias >= 1) { - m = ((value * c) - 1) * Math.pow(2, mLen) - e = e + eBias - } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) - e = 0 - } - } - - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} - - e = (e << mLen) | m - eLen += mLen - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} - - buffer[offset + i - d] |= s * 128 -} - - -/***/ }), -/* 176 */ -/***/ (function(module, exports) { - -/* (ignored) */ - -/***/ }), -/* 177 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var Buffer = __webpack_require__(20).Buffer; -var util = __webpack_require__(178); - -function copyBuffer(src, target, offset) { - src.copy(target, offset); -} - -module.exports = function () { - function BufferList() { - _classCallCheck(this, BufferList); - - this.head = null; - this.tail = null; - this.length = 0; - } - - BufferList.prototype.push = function push(v) { - var entry = { data: v, next: null }; - if (this.length > 0) this.tail.next = entry;else this.head = entry; - this.tail = entry; - ++this.length; - }; - - BufferList.prototype.unshift = function unshift(v) { - var entry = { data: v, next: this.head }; - if (this.length === 0) this.tail = entry; - this.head = entry; - ++this.length; - }; - - BufferList.prototype.shift = function shift() { - if (this.length === 0) return; - var ret = this.head.data; - if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; - --this.length; - return ret; - }; - - BufferList.prototype.clear = function clear() { - this.head = this.tail = null; - this.length = 0; - }; - - BufferList.prototype.join = function join(s) { - if (this.length === 0) return ''; - var p = this.head; - var ret = '' + p.data; - while (p = p.next) { - ret += s + p.data; - }return ret; - }; - - BufferList.prototype.concat = function concat(n) { - if (this.length === 0) return Buffer.alloc(0); - if (this.length === 1) return this.head.data; - var ret = Buffer.allocUnsafe(n >>> 0); - var p = this.head; - var i = 0; - while (p) { - copyBuffer(p.data, ret, i); - i += p.data.length; - p = p.next; - } - return ret; - }; - - return BufferList; -}(); - -if (util && util.inspect && util.inspect.custom) { - module.exports.prototype[util.inspect.custom] = function () { - var obj = util.inspect({ length: this.length }); - return this.constructor.name + ' ' + obj; - }; -} - -/***/ }), -/* 178 */ -/***/ (function(module, exports) { - -/* (ignored) */ - -/***/ }), -/* 179 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(global) {var scope = (typeof global !== "undefined" && global) || - (typeof self !== "undefined" && self) || - window; -var apply = Function.prototype.apply; - -// DOM APIs, for completeness - -exports.setTimeout = function() { - return new Timeout(apply.call(setTimeout, scope, arguments), clearTimeout); -}; -exports.setInterval = function() { - return new Timeout(apply.call(setInterval, scope, arguments), clearInterval); -}; -exports.clearTimeout = -exports.clearInterval = function(timeout) { - if (timeout) { - timeout.close(); - } -}; - -function Timeout(id, clearFn) { - this._id = id; - this._clearFn = clearFn; -} -Timeout.prototype.unref = Timeout.prototype.ref = function() {}; -Timeout.prototype.close = function() { - this._clearFn.call(scope, this._id); -}; - -// Does not start the time, just sets up the members needed. -exports.enroll = function(item, msecs) { - clearTimeout(item._idleTimeoutId); - item._idleTimeout = msecs; -}; - -exports.unenroll = function(item) { - clearTimeout(item._idleTimeoutId); - item._idleTimeout = -1; -}; - -exports._unrefActive = exports.active = function(item) { - clearTimeout(item._idleTimeoutId); - - var msecs = item._idleTimeout; - if (msecs >= 0) { - item._idleTimeoutId = setTimeout(function onTimeout() { - if (item._onTimeout) - item._onTimeout(); - }, msecs); - } -}; - -// setimmediate attaches itself to the global object -__webpack_require__(180); -// On some exotic environments, it's not clear which object `setimmediate` was -// able to install onto. Search each possibility in the same order as the -// `setimmediate` library. -exports.setImmediate = (typeof self !== "undefined" && self.setImmediate) || - (typeof global !== "undefined" && global.setImmediate) || - (this && this.setImmediate); -exports.clearImmediate = (typeof self !== "undefined" && self.clearImmediate) || - (typeof global !== "undefined" && global.clearImmediate) || - (this && this.clearImmediate); - -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(11))) - -/***/ }), -/* 180 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(global, process) {(function (global, undefined) { - "use strict"; - - if (global.setImmediate) { - return; - } - - var nextHandle = 1; // Spec says greater than zero - var tasksByHandle = {}; - var currentlyRunningATask = false; - var doc = global.document; - var registerImmediate; - - function setImmediate(callback) { - // Callback can either be a function or a string - if (typeof callback !== "function") { - callback = new Function("" + callback); - } - // Copy function arguments - var args = new Array(arguments.length - 1); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i + 1]; - } - // Store and register the task - var task = { callback: callback, args: args }; - tasksByHandle[nextHandle] = task; - registerImmediate(nextHandle); - return nextHandle++; - } - - function clearImmediate(handle) { - delete tasksByHandle[handle]; - } - - function run(task) { - var callback = task.callback; - var args = task.args; - switch (args.length) { - case 0: - callback(); - break; - case 1: - callback(args[0]); - break; - case 2: - callback(args[0], args[1]); - break; - case 3: - callback(args[0], args[1], args[2]); - break; - default: - callback.apply(undefined, args); - break; - } - } - - function runIfPresent(handle) { - // From the spec: "Wait until any invocations of this algorithm started before this one have completed." - // So if we're currently running a task, we'll need to delay this invocation. - if (currentlyRunningATask) { - // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a - // "too much recursion" error. - setTimeout(runIfPresent, 0, handle); - } else { - var task = tasksByHandle[handle]; - if (task) { - currentlyRunningATask = true; - try { - run(task); - } finally { - clearImmediate(handle); - currentlyRunningATask = false; - } - } - } - } - - function installNextTickImplementation() { - registerImmediate = function(handle) { - process.nextTick(function () { runIfPresent(handle); }); - }; - } - - function canUsePostMessage() { - // The test against `importScripts` prevents this implementation from being installed inside a web worker, - // where `global.postMessage` means something completely different and can't be used for this purpose. - if (global.postMessage && !global.importScripts) { - var postMessageIsAsynchronous = true; - var oldOnMessage = global.onmessage; - global.onmessage = function() { - postMessageIsAsynchronous = false; - }; - global.postMessage("", "*"); - global.onmessage = oldOnMessage; - return postMessageIsAsynchronous; - } - } - - function installPostMessageImplementation() { - // Installs an event handler on `global` for the `message` event: see - // * https://developer.mozilla.org/en/DOM/window.postMessage - // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages - - var messagePrefix = "setImmediate$" + Math.random() + "$"; - var onGlobalMessage = function(event) { - if (event.source === global && - typeof event.data === "string" && - event.data.indexOf(messagePrefix) === 0) { - runIfPresent(+event.data.slice(messagePrefix.length)); - } - }; - - if (global.addEventListener) { - global.addEventListener("message", onGlobalMessage, false); - } else { - global.attachEvent("onmessage", onGlobalMessage); - } - - registerImmediate = function(handle) { - global.postMessage(messagePrefix + handle, "*"); - }; - } - - function installMessageChannelImplementation() { - var channel = new MessageChannel(); - channel.port1.onmessage = function(event) { - var handle = event.data; - runIfPresent(handle); - }; - - registerImmediate = function(handle) { - channel.port2.postMessage(handle); - }; - } - - function installReadyStateChangeImplementation() { - var html = doc.documentElement; - registerImmediate = function(handle) { - // Create a - * "; - * var result = util.encodeHTMLEntity(htmlEntityString); - * //"<script> alert('test');</script><a href='test'>" - */ - function encodeHTMLEntity(html) { - var entities = { - '"': 'quot', - '&': 'amp', - '<': 'lt', - '>': 'gt', - '\'': '#39' - }; - - return html.replace(/[<>&"']/g, function(m0) { - return entities[m0] ? '&' + entities[m0] + ';' : m0; - }); - } - - /** - * Return whether the string capable to transform into plain string is in the given string or not. - * @param {String} string - test string - * @memberof tui.util - * @returns {boolean} - */ - function hasEncodableString(string) { - return (/[<>&"']/).test(string); - } - - /** - * Return duplicate charters - * @param {string} operandStr1 The operand string - * @param {string} operandStr2 The operand string - * @private - * @memberof tui.util - * @returns {string} - * @example - * //-- #1. Get Module --// - * var util = require('tui-code-snippet'); // node, commonjs - * var util = tui.util; // distribution file - * - * //-- #2. Use property --// - * util.getDuplicatedChar('fe dev', 'nhn entertainment'); // 'e' - * util.getDuplicatedChar('fdsa', 'asdf'); // 'asdf' - */ - function getDuplicatedChar(operandStr1, operandStr2) { - var i = 0; - var len = operandStr1.length; - var pool = {}; - var dupl, key; - - for (; i < len; i += 1) { - key = operandStr1.charAt(i); - pool[key] = 1; - } - - for (i = 0, len = operandStr2.length; i < len; i += 1) { - key = operandStr2.charAt(i); - if (pool[key]) { - pool[key] += 1; - } - } - - pool = collection.filter(pool, function(item) { - return item > 1; - }); - - pool = object.keys(pool).sort(); - dupl = pool.join(''); - - return dupl; - } - - module.exports = { - decodeHTMLEntity: decodeHTMLEntity, - encodeHTMLEntity: encodeHTMLEntity, - hasEncodableString: hasEncodableString, - getDuplicatedChar: getDuplicatedChar - }; - - -/***/ }), -/* 8 */ -/***/ (function(module, exports) { - - /** - * @fileoverview collections of some technic methods. - * @author NHN. - * FE Development Lab - */ - - 'use strict'; - - var tricks = {}; - var aps = Array.prototype.slice; - - /** - * Creates a debounced function that delays invoking fn until after delay milliseconds has elapsed - * since the last time the debouced function was invoked. - * @param {function} fn The function to debounce. - * @param {number} [delay=0] The number of milliseconds to delay - * @memberof tui.util - * @returns {function} debounced function. - * @example - * //-- #1. Get Module --// - * var util = require('tui-code-snippet'); // node, commonjs - * var util = tui.util; // distribution file - * - * //-- #2. Use property --// - * function someMethodToInvokeDebounced() {} - * - * var debounced = util.debounce(someMethodToInvokeDebounced, 300); - * - * // invoke repeatedly - * debounced(); - * debounced(); - * debounced(); - * debounced(); - * debounced(); - * debounced(); // last invoke of debounced() - * - * // invoke someMethodToInvokeDebounced() after 300 milliseconds. - */ - function debounce(fn, delay) { - var timer, args; - - /* istanbul ignore next */ - delay = delay || 0; - - function debounced() { // eslint-disable-line require-jsdoc - args = aps.call(arguments); - - window.clearTimeout(timer); - timer = window.setTimeout(function() { - fn.apply(null, args); - }, delay); - } - - return debounced; - } - - /** - * return timestamp - * @memberof tui.util - * @returns {number} The number of milliseconds from Jan. 1970 00:00:00 (GMT) - */ - function timestamp() { - return Number(new Date()); - } - - /** - * Creates a throttled function that only invokes fn at most once per every interval milliseconds. - * - * You can use this throttle short time repeatedly invoking functions. (e.g MouseMove, Resize ...) - * - * if you need reuse throttled method. you must remove slugs (e.g. flag variable) related with throttling. - * @param {function} fn function to throttle - * @param {number} [interval=0] the number of milliseconds to throttle invocations to. - * @memberof tui.util - * @returns {function} throttled function - * @example - * //-- #1. Get Module --// - * var util = require('tui-code-snippet'); // node, commonjs - * var util = tui.util; // distribution file - * - * //-- #2. Use property --// - * function someMethodToInvokeThrottled() {} - * - * var throttled = util.throttle(someMethodToInvokeThrottled, 300); - * - * // invoke repeatedly - * throttled(); // invoke (leading) - * throttled(); - * throttled(); // invoke (near 300 milliseconds) - * throttled(); - * throttled(); - * throttled(); // invoke (near 600 milliseconds) - * // ... - * // invoke (trailing) - * - * // if you need reuse throttled method. then invoke reset() - * throttled.reset(); - */ - function throttle(fn, interval) { - var base; - var isLeading = true; - var tick = function(_args) { - fn.apply(null, _args); - base = null; - }; - var debounced, stamp, args; - - /* istanbul ignore next */ - interval = interval || 0; - - debounced = tricks.debounce(tick, interval); - - function throttled() { // eslint-disable-line require-jsdoc - args = aps.call(arguments); - - if (isLeading) { - tick(args); - isLeading = false; - - return; - } - - stamp = tricks.timestamp(); - - base = base || stamp; - - // pass array directly because `debounce()`, `tick()` are already use - // `apply()` method to invoke developer's `fn` handler. - // - // also, this `debounced` line invoked every time for implements - // `trailing` features. - debounced(args); - - if ((stamp - base) >= interval) { - tick(args); - } - } - - function reset() { // eslint-disable-line require-jsdoc - isLeading = true; - base = null; - } - - throttled.reset = reset; - - return throttled; - } - - tricks.timestamp = timestamp; - tricks.debounce = debounce; - tricks.throttle = throttle; - - module.exports = tricks; - - -/***/ }), -/* 9 */ -/***/ (function(module, exports, __webpack_require__) { - - /** - * @fileoverview This module has some functions for handling object as collection. - * @author NHN. - * FE Development Lab - */ - 'use strict'; - - var object = __webpack_require__(1); - var collection = __webpack_require__(4); - var type = __webpack_require__(2); - var ms7days = 7 * 24 * 60 * 60 * 1000; - - /** - * Check if the date has passed 7 days - * @param {number} date - milliseconds - * @returns {boolean} - * @ignore - */ - function isExpired(date) { - var now = new Date().getTime(); - - return now - date > ms7days; - } - - /** - * Send hostname on DOMContentLoaded. - * To prevent hostname set tui.usageStatistics to false. - * @param {string} appName - application name - * @param {string} trackingId - GA tracking ID - * @ignore - */ - function sendHostname(appName, trackingId) { - var url = 'https://www.google-analytics.com/collect'; - var hostname = location.hostname; - var hitType = 'event'; - var eventCategory = 'use'; - var applicationKeyForStorage = 'TOAST UI ' + appName + ' for ' + hostname + ': Statistics'; - var date = window.localStorage.getItem(applicationKeyForStorage); - - // skip if the flag is defined and is set to false explicitly - if (!type.isUndefined(window.tui) && window.tui.usageStatistics === false) { - return; - } - - // skip if not pass seven days old - if (date && !isExpired(date)) { - return; - } - - window.localStorage.setItem(applicationKeyForStorage, new Date().getTime()); - - setTimeout(function() { - if (document.readyState === 'interactive' || document.readyState === 'complete') { - imagePing(url, { - v: 1, - t: hitType, - tid: trackingId, - cid: hostname, - dp: hostname, - dh: appName, - el: appName, - ec: eventCategory - }); - } - }, 1000); - } - - /** - * Request image ping. - * @param {String} url url for ping request - * @param {Object} trackingInfo infos for make query string - * @returns {HTMLElement} - * @memberof tui.util - * @example - * //-- #1. Get Module --// - * var util = require('tui-code-snippet'); // node, commonjs - * var util = tui.util; // distribution file - * - * //-- #2. Use property --// - * util.imagePing('https://www.google-analytics.com/collect', { - * v: 1, - * t: 'event', - * tid: 'trackingid', - * cid: 'cid', - * dp: 'dp', - * dh: 'dh' - * }); - */ - function imagePing(url, trackingInfo) { - var queryString = collection.map(object.keys(trackingInfo), function(key, index) { - var startWith = index === 0 ? '' : '&'; - - return startWith + key + '=' + trackingInfo[key]; - }).join(''); - var trackingElement = document.createElement('img'); - - trackingElement.src = url + '?' + queryString; - - trackingElement.style.display = 'none'; - document.body.appendChild(trackingElement); - document.body.removeChild(trackingElement); - - return trackingElement; - } - - module.exports = { - imagePing: imagePing, - sendHostname: sendHostname - }; - - -/***/ }), -/* 10 */ -/***/ (function(module, exports) { - - /** - * @fileoverview This module detects the kind of well-known browser and version. - * @author NHN. - * FE Development Lab - */ - - 'use strict'; - - /** - * This object has an information that indicate the kind of browser.
    - * The list below is a detectable browser list. - * - ie8 ~ ie11 - * - chrome - * - firefox - * - safari - * - edge - * @memberof tui.util - * @example - * //-- #1. Get Module --// - * var util = require('tui-code-snippet'); // node, commonjs - * var util = tui.util; // distribution file - * - * //-- #2. Use property --// - * util.browser.chrome === true; // chrome - * util.browser.firefox === true; // firefox - * util.browser.safari === true; // safari - * util.browser.msie === true; // IE - * util.browser.edge === true; // edge - * util.browser.others === true; // other browser - * util.browser.version; // browser version - */ - var browser = { - chrome: false, - firefox: false, - safari: false, - msie: false, - edge: false, - others: false, - version: 0 - }; - - if (window && window.navigator) { - detectBrowser(); - } - - /** - * Detect the browser. - * @private - */ - function detectBrowser() { - var nav = window.navigator; - var appName = nav.appName.replace(/\s/g, '_'); - var userAgent = nav.userAgent; - - var rIE = /MSIE\s([0-9]+[.0-9]*)/; - var rIE11 = /Trident.*rv:11\./; - var rEdge = /Edge\/(\d+)\./; - var versionRegex = { - firefox: /Firefox\/(\d+)\./, - chrome: /Chrome\/(\d+)\./, - safari: /Version\/([\d.]+).*Safari\/(\d+)/ - }; - - var key, tmp; - - var detector = { - Microsoft_Internet_Explorer: function() { // eslint-disable-line camelcase - var detectedVersion = userAgent.match(rIE); - - if (detectedVersion) { // ie8 ~ ie10 - browser.msie = true; - browser.version = parseFloat(detectedVersion[1]); - } else { // no version information - browser.others = true; - } - }, - Netscape: function() { // eslint-disable-line complexity - var detected = false; - - if (rIE11.exec(userAgent)) { - browser.msie = true; - browser.version = 11; - detected = true; - } else if (rEdge.exec(userAgent)) { - browser.edge = true; - browser.version = userAgent.match(rEdge)[1]; - detected = true; - } else { - for (key in versionRegex) { - if (versionRegex.hasOwnProperty(key)) { - tmp = userAgent.match(versionRegex[key]); - if (tmp && tmp.length > 1) { // eslint-disable-line max-depth - browser[key] = detected = true; - browser.version = parseFloat(tmp[1] || 0); - break; - } - } - } - } - if (!detected) { - browser.others = true; - } - } - }; - - var fn = detector[appName]; - - if (fn) { - detector[appName](); - } - } - - module.exports = browser; - - -/***/ }), -/* 11 */ -/***/ (function(module, exports, __webpack_require__) { - - /** - * @fileoverview This module has some methods for handling popup-window - * @author NHN. - * FE Development Lab - */ - - 'use strict'; - - var collection = __webpack_require__(4); - var type = __webpack_require__(2); - var func = __webpack_require__(5); - var browser = __webpack_require__(10); - var object = __webpack_require__(1); - - var popupId = 0; - - /** - * Popup management class - * @constructor - * @memberof tui.util - * @example - * // node, commonjs - * var popup = require('tui-code-snippet').popup; - * @example - * // distribution file, script - * - * - * - */ - function CustomEvents() { - /** - * @type {HandlerItem[]} - */ - this.events = null; - - /** - * only for checking specific context event was binded - * @type {object[]} - */ - this.contexts = null; - } - - /** - * Mixin custom events feature to specific constructor - * @param {function} func - constructor - * @example - * //-- #1. Get Module --// - * var CustomEvents = require('tui-code-snippet').CustomEvents; // node, commonjs - * var CustomEvents = tui.util.CustomEvents; // distribution file - * - * //-- #2. Use property --// - * var model; - * function Model() { - * this.name = ''; - * } - * CustomEvents.mixin(Model); - * - * model = new Model(); - * model.on('change', function() { this.name = 'model'; }, this); - * model.fire('change'); - * alert(model.name); // 'model'; - */ - CustomEvents.mixin = function(func) { - object.extend(func.prototype, CustomEvents.prototype); - }; - - /** - * Get HandlerItem object - * @param {function} handler - handler function - * @param {object} [context] - context for handler - * @returns {HandlerItem} HandlerItem object - * @private - */ - CustomEvents.prototype._getHandlerItem = function(handler, context) { - var item = {handler: handler}; - - if (context) { - item.context = context; - } - - return item; - }; - - /** - * Get event object safely - * @param {string} [eventName] - create sub event map if not exist. - * @returns {(object|array)} event object. if you supplied `eventName` - * parameter then make new array and return it - * @private - */ - CustomEvents.prototype._safeEvent = function(eventName) { - var events = this.events; - var byName; - - if (!events) { - events = this.events = {}; - } - - if (eventName) { - byName = events[eventName]; - - if (!byName) { - byName = []; - events[eventName] = byName; - } - - events = byName; - } - - return events; - }; - - /** - * Get context array safely - * @returns {array} context array - * @private - */ - CustomEvents.prototype._safeContext = function() { - var context = this.contexts; - - if (!context) { - context = this.contexts = []; - } - - return context; - }; - - /** - * Get index of context - * @param {object} ctx - context that used for bind custom event - * @returns {number} index of context - * @private - */ - CustomEvents.prototype._indexOfContext = function(ctx) { - var context = this._safeContext(); - var index = 0; - - while (context[index]) { - if (ctx === context[index][0]) { - return index; - } - - index += 1; - } - - return -1; - }; - - /** - * Memorize supplied context for recognize supplied object is context or - * name: handler pair object when off() - * @param {object} ctx - context object to memorize - * @private - */ - CustomEvents.prototype._memorizeContext = function(ctx) { - var context, index; - - if (!type.isExisty(ctx)) { - return; - } - - context = this._safeContext(); - index = this._indexOfContext(ctx); - - if (index > -1) { - context[index][1] += 1; - } else { - context.push([ctx, 1]); - } - }; - - /** - * Forget supplied context object - * @param {object} ctx - context object to forget - * @private - */ - CustomEvents.prototype._forgetContext = function(ctx) { - var context, contextIndex; - - if (!type.isExisty(ctx)) { - return; - } - - context = this._safeContext(); - contextIndex = this._indexOfContext(ctx); - - if (contextIndex > -1) { - context[contextIndex][1] -= 1; - - if (context[contextIndex][1] <= 0) { - context.splice(contextIndex, 1); - } - } - }; - - /** - * Bind event handler - * @param {(string|{name:string, handler:function})} eventName - custom - * event name or an object {eventName: handler} - * @param {(function|object)} [handler] - handler function or context - * @param {object} [context] - context for binding - * @private - */ - CustomEvents.prototype._bindEvent = function(eventName, handler, context) { - var events = this._safeEvent(eventName); - this._memorizeContext(context); - events.push(this._getHandlerItem(handler, context)); - }; - - /** - * Bind event handlers - * @param {(string|{name:string, handler:function})} eventName - custom - * event name or an object {eventName: handler} - * @param {(function|object)} [handler] - handler function or context - * @param {object} [context] - context for binding - * //-- #1. Get Module --// - * var CustomEvents = require('tui-code-snippet').CustomEvents; // node, commonjs - * var CustomEvents = tui.util.CustomEvents; // distribution file - * - * //-- #2. Use property --// - * // # 2.1 Basic Usage - * CustomEvents.on('onload', handler); - * - * // # 2.2 With context - * CustomEvents.on('onload', handler, myObj); - * - * // # 2.3 Bind by object that name, handler pairs - * CustomEvents.on({ - * 'play': handler, - * 'pause': handler2 - * }); - * - * // # 2.4 Bind by object that name, handler pairs with context object - * CustomEvents.on({ - * 'play': handler - * }, myObj); - */ - CustomEvents.prototype.on = function(eventName, handler, context) { - var self = this; - - if (type.isString(eventName)) { - // [syntax 1, 2] - eventName = eventName.split(R_EVENTNAME_SPLIT); - collection.forEach(eventName, function(name) { - self._bindEvent(name, handler, context); - }); - } else if (type.isObject(eventName)) { - // [syntax 3, 4] - context = handler; - collection.forEach(eventName, function(func, name) { - self.on(name, func, context); - }); - } - }; - - /** - * Bind one-shot event handlers - * @param {(string|{name:string,handler:function})} eventName - custom - * event name or an object {eventName: handler} - * @param {function|object} [handler] - handler function or context - * @param {object} [context] - context for binding - */ - CustomEvents.prototype.once = function(eventName, handler, context) { - var self = this; - - if (type.isObject(eventName)) { - context = handler; - collection.forEach(eventName, function(func, name) { - self.once(name, func, context); - }); - - return; - } - - function onceHandler() { // eslint-disable-line require-jsdoc - handler.apply(context, arguments); - self.off(eventName, onceHandler, context); - } - - this.on(eventName, onceHandler, context); - }; - - /** - * Splice supplied array by callback result - * @param {array} arr - array to splice - * @param {function} predicate - function return boolean - * @private - */ - CustomEvents.prototype._spliceMatches = function(arr, predicate) { - var i = 0; - var len; - - if (!type.isArray(arr)) { - return; - } - - for (len = arr.length; i < len; i += 1) { - if (predicate(arr[i]) === true) { - arr.splice(i, 1); - len -= 1; - i -= 1; - } - } - }; - - /** - * Get matcher for unbind specific handler events - * @param {function} handler - handler function - * @returns {function} handler matcher - * @private - */ - CustomEvents.prototype._matchHandler = function(handler) { - var self = this; - - return function(item) { - var needRemove = handler === item.handler; - - if (needRemove) { - self._forgetContext(item.context); - } - - return needRemove; - }; - }; - - /** - * Get matcher for unbind specific context events - * @param {object} context - context - * @returns {function} object matcher - * @private - */ - CustomEvents.prototype._matchContext = function(context) { - var self = this; - - return function(item) { - var needRemove = context === item.context; - - if (needRemove) { - self._forgetContext(item.context); - } - - return needRemove; - }; - }; - - /** - * Get matcher for unbind specific hander, context pair events - * @param {function} handler - handler function - * @param {object} context - context - * @returns {function} handler, context matcher - * @private - */ - CustomEvents.prototype._matchHandlerAndContext = function(handler, context) { - var self = this; - - return function(item) { - var matchHandler = (handler === item.handler); - var matchContext = (context === item.context); - var needRemove = (matchHandler && matchContext); - - if (needRemove) { - self._forgetContext(item.context); - } - - return needRemove; - }; - }; - - /** - * Unbind event by event name - * @param {string} eventName - custom event name to unbind - * @param {function} [handler] - handler function - * @private - */ - CustomEvents.prototype._offByEventName = function(eventName, handler) { - var self = this; - var forEach = collection.forEachArray; - var andByHandler = type.isFunction(handler); - var matchHandler = self._matchHandler(handler); - - eventName = eventName.split(R_EVENTNAME_SPLIT); - - forEach(eventName, function(name) { - var handlerItems = self._safeEvent(name); - - if (andByHandler) { - self._spliceMatches(handlerItems, matchHandler); - } else { - forEach(handlerItems, function(item) { - self._forgetContext(item.context); - }); - - self.events[name] = []; - } - }); - }; - - /** - * Unbind event by handler function - * @param {function} handler - handler function - * @private - */ - CustomEvents.prototype._offByHandler = function(handler) { - var self = this; - var matchHandler = this._matchHandler(handler); - - collection.forEach(this._safeEvent(), function(handlerItems) { - self._spliceMatches(handlerItems, matchHandler); - }); - }; - - /** - * Unbind event by object(name: handler pair object or context object) - * @param {object} obj - context or {name: handler} pair object - * @param {function} handler - handler function - * @private - */ - CustomEvents.prototype._offByObject = function(obj, handler) { - var self = this; - var matchFunc; - - if (this._indexOfContext(obj) < 0) { - collection.forEach(obj, function(func, name) { - self.off(name, func); - }); - } else if (type.isString(handler)) { - matchFunc = this._matchContext(obj); - - self._spliceMatches(this._safeEvent(handler), matchFunc); - } else if (type.isFunction(handler)) { - matchFunc = this._matchHandlerAndContext(handler, obj); - - collection.forEach(this._safeEvent(), function(handlerItems) { - self._spliceMatches(handlerItems, matchFunc); - }); - } else { - matchFunc = this._matchContext(obj); - - collection.forEach(this._safeEvent(), function(handlerItems) { - self._spliceMatches(handlerItems, matchFunc); - }); - } - }; - - /** - * Unbind custom events - * @param {(string|object|function)} eventName - event name or context or - * {name: handler} pair object or handler function - * @param {(function)} handler - handler function - * @example - * //-- #1. Get Module --// - * var CustomEvents = require('tui-code-snippet').CustomEvents; // node, commonjs - * var CustomEvents = tui.util.CustomEvents; // distribution file - * - * //-- #2. Use property --// - * // # 2.1 off by event name - * CustomEvents.off('onload'); - * - * // # 2.2 off by event name and handler - * CustomEvents.off('play', handler); - * - * // # 2.3 off by handler - * CustomEvents.off(handler); - * - * // # 2.4 off by context - * CustomEvents.off(myObj); - * - * // # 2.5 off by context and handler - * CustomEvents.off(myObj, handler); - * - * // # 2.6 off by context and event name - * CustomEvents.off(myObj, 'onload'); - * - * // # 2.7 off by an Object. that is {eventName: handler} - * CustomEvents.off({ - * 'play': handler, - * 'pause': handler2 - * }); - * - * // # 2.8 off the all events - * CustomEvents.off(); - */ - CustomEvents.prototype.off = function(eventName, handler) { - if (type.isString(eventName)) { - // [syntax 1, 2] - this._offByEventName(eventName, handler); - } else if (!arguments.length) { - // [syntax 8] - this.events = {}; - this.contexts = []; - } else if (type.isFunction(eventName)) { - // [syntax 3] - this._offByHandler(eventName); - } else if (type.isObject(eventName)) { - // [syntax 4, 5, 6] - this._offByObject(eventName, handler); - } - }; - - /** - * Fire custom event - * @param {string} eventName - name of custom event - */ - CustomEvents.prototype.fire = function(eventName) { // eslint-disable-line - this.invoke.apply(this, arguments); - }; - - /** - * Fire a event and returns the result of operation 'boolean AND' with all - * listener's results. - * - * So, It is different from {@link CustomEvents#fire}. - * - * In service code, use this as a before event in component level usually - * for notifying that the event is cancelable. - * @param {string} eventName - Custom event name - * @param {...*} data - Data for event - * @returns {boolean} The result of operation 'boolean AND' - * @example - * var map = new Map(); - * map.on({ - * 'beforeZoom': function() { - * // It should cancel the 'zoom' event by some conditions. - * if (that.disabled && this.getState()) { - * return false; - * } - * return true; - * } - * }); - * - * if (this.invoke('beforeZoom')) { // check the result of 'beforeZoom' - * // if true, - * // doSomething - * } - */ - CustomEvents.prototype.invoke = function(eventName) { - var events, args, index, item; - - if (!this.hasListener(eventName)) { - return true; - } - - events = this._safeEvent(eventName); - args = Array.prototype.slice.call(arguments, 1); - index = 0; - - while (events[index]) { - item = events[index]; - - if (item.handler.apply(item.context, args) === false) { - return false; - } - - index += 1; - } - - return true; - }; - - /** - * Return whether at least one of the handlers is registered in the given - * event name. - * @param {string} eventName - Custom event name - * @returns {boolean} Is there at least one handler in event name? - */ - CustomEvents.prototype.hasListener = function(eventName) { - return this.getListenerLength(eventName) > 0; - }; - - /** - * Return a count of events registered. - * @param {string} eventName - Custom event name - * @returns {number} number of event - */ - CustomEvents.prototype.getListenerLength = function(eventName) { - var events = this._safeEvent(eventName); - - return events.length; - }; - - module.exports = CustomEvents; - - -/***/ }), -/* 17 */ -/***/ (function(module, exports, __webpack_require__) { - - /** - * @fileoverview This module provides a Enum Constructor. - * @author NHN. - * FE Development Lab - * @example - * // node, commonjs - * var Enum = require('tui-code-snippet').Enum; - * @example - * // distribution file, script - * - * - * - * - * - *
    "; - * var result = util.encodeHTMLEntity(htmlEntityString); - * //"<script> alert('test');</script><a href='test'>" - */ - function encodeHTMLEntity(html) { - var entities = { - '"': 'quot', - '&': 'amp', - '<': 'lt', - '>': 'gt', - '\'': '#39' - }; - - return html.replace(/[<>&"']/g, function(m0) { - return entities[m0] ? '&' + entities[m0] + ';' : m0; - }); - } - - /** - * Return whether the string capable to transform into plain string is in the given string or not. - * @param {String} string - test string - * @memberof tui.util - * @returns {boolean} - */ - function hasEncodableString(string) { - return (/[<>&"']/).test(string); - } - - /** - * Return duplicate charters - * @param {string} operandStr1 The operand string - * @param {string} operandStr2 The operand string - * @private - * @memberof tui.util - * @returns {string} - * @example - * //-- #1. Get Module --// - * var util = require('tui-code-snippet'); // node, commonjs - * var util = tui.util; // distribution file - * - * //-- #2. Use property --// - * util.getDuplicatedChar('fe dev', 'nhn entertainment'); // 'e' - * util.getDuplicatedChar('fdsa', 'asdf'); // 'asdf' - */ - function getDuplicatedChar(operandStr1, operandStr2) { - var i = 0; - var len = operandStr1.length; - var pool = {}; - var dupl, key; - - for (; i < len; i += 1) { - key = operandStr1.charAt(i); - pool[key] = 1; - } - - for (i = 0, len = operandStr2.length; i < len; i += 1) { - key = operandStr2.charAt(i); - if (pool[key]) { - pool[key] += 1; - } - } - - pool = collection.filter(pool, function(item) { - return item > 1; - }); - - pool = object.keys(pool).sort(); - dupl = pool.join(''); - - return dupl; - } - - module.exports = { - decodeHTMLEntity: decodeHTMLEntity, - encodeHTMLEntity: encodeHTMLEntity, - hasEncodableString: hasEncodableString, - getDuplicatedChar: getDuplicatedChar - }; - - -/***/ }), -/* 8 */ -/***/ (function(module, exports) { - - /** - * @fileoverview collections of some technic methods. - * @author NHN. - * FE Development Lab - */ - - 'use strict'; - - var tricks = {}; - var aps = Array.prototype.slice; - - /** - * Creates a debounced function that delays invoking fn until after delay milliseconds has elapsed - * since the last time the debouced function was invoked. - * @param {function} fn The function to debounce. - * @param {number} [delay=0] The number of milliseconds to delay - * @memberof tui.util - * @returns {function} debounced function. - * @example - * //-- #1. Get Module --// - * var util = require('tui-code-snippet'); // node, commonjs - * var util = tui.util; // distribution file - * - * //-- #2. Use property --// - * function someMethodToInvokeDebounced() {} - * - * var debounced = util.debounce(someMethodToInvokeDebounced, 300); - * - * // invoke repeatedly - * debounced(); - * debounced(); - * debounced(); - * debounced(); - * debounced(); - * debounced(); // last invoke of debounced() - * - * // invoke someMethodToInvokeDebounced() after 300 milliseconds. - */ - function debounce(fn, delay) { - var timer, args; - - /* istanbul ignore next */ - delay = delay || 0; - - function debounced() { // eslint-disable-line require-jsdoc - args = aps.call(arguments); - - window.clearTimeout(timer); - timer = window.setTimeout(function() { - fn.apply(null, args); - }, delay); - } - - return debounced; - } - - /** - * return timestamp - * @memberof tui.util - * @returns {number} The number of milliseconds from Jan. 1970 00:00:00 (GMT) - */ - function timestamp() { - return Number(new Date()); - } - - /** - * Creates a throttled function that only invokes fn at most once per every interval milliseconds. - * - * You can use this throttle short time repeatedly invoking functions. (e.g MouseMove, Resize ...) - * - * if you need reuse throttled method. you must remove slugs (e.g. flag variable) related with throttling. - * @param {function} fn function to throttle - * @param {number} [interval=0] the number of milliseconds to throttle invocations to. - * @memberof tui.util - * @returns {function} throttled function - * @example - * //-- #1. Get Module --// - * var util = require('tui-code-snippet'); // node, commonjs - * var util = tui.util; // distribution file - * - * //-- #2. Use property --// - * function someMethodToInvokeThrottled() {} - * - * var throttled = util.throttle(someMethodToInvokeThrottled, 300); - * - * // invoke repeatedly - * throttled(); // invoke (leading) - * throttled(); - * throttled(); // invoke (near 300 milliseconds) - * throttled(); - * throttled(); - * throttled(); // invoke (near 600 milliseconds) - * // ... - * // invoke (trailing) - * - * // if you need reuse throttled method. then invoke reset() - * throttled.reset(); - */ - function throttle(fn, interval) { - var base; - var isLeading = true; - var tick = function(_args) { - fn.apply(null, _args); - base = null; - }; - var debounced, stamp, args; - - /* istanbul ignore next */ - interval = interval || 0; - - debounced = tricks.debounce(tick, interval); - - function throttled() { // eslint-disable-line require-jsdoc - args = aps.call(arguments); - - if (isLeading) { - tick(args); - isLeading = false; - - return; - } - - stamp = tricks.timestamp(); - - base = base || stamp; - - // pass array directly because `debounce()`, `tick()` are already use - // `apply()` method to invoke developer's `fn` handler. - // - // also, this `debounced` line invoked every time for implements - // `trailing` features. - debounced(args); - - if ((stamp - base) >= interval) { - tick(args); - } - } - - function reset() { // eslint-disable-line require-jsdoc - isLeading = true; - base = null; - } - - throttled.reset = reset; - - return throttled; - } - - tricks.timestamp = timestamp; - tricks.debounce = debounce; - tricks.throttle = throttle; - - module.exports = tricks; - - -/***/ }), -/* 9 */ -/***/ (function(module, exports, __webpack_require__) { - - /** - * @fileoverview This module has some functions for handling object as collection. - * @author NHN. - * FE Development Lab - */ - 'use strict'; - - var object = __webpack_require__(1); - var collection = __webpack_require__(4); - var type = __webpack_require__(2); - var ms7days = 7 * 24 * 60 * 60 * 1000; - - /** - * Check if the date has passed 7 days - * @param {number} date - milliseconds - * @returns {boolean} - * @ignore - */ - function isExpired(date) { - var now = new Date().getTime(); - - return now - date > ms7days; - } - - /** - * Send hostname on DOMContentLoaded. - * To prevent hostname set tui.usageStatistics to false. - * @param {string} appName - application name - * @param {string} trackingId - GA tracking ID - * @ignore - */ - function sendHostname(appName, trackingId) { - var url = 'https://www.google-analytics.com/collect'; - var hostname = location.hostname; - var hitType = 'event'; - var eventCategory = 'use'; - var applicationKeyForStorage = 'TOAST UI ' + appName + ' for ' + hostname + ': Statistics'; - var date = window.localStorage.getItem(applicationKeyForStorage); - - // skip if the flag is defined and is set to false explicitly - if (!type.isUndefined(window.tui) && window.tui.usageStatistics === false) { - return; - } - - // skip if not pass seven days old - if (date && !isExpired(date)) { - return; - } - - window.localStorage.setItem(applicationKeyForStorage, new Date().getTime()); - - setTimeout(function() { - if (document.readyState === 'interactive' || document.readyState === 'complete') { - imagePing(url, { - v: 1, - t: hitType, - tid: trackingId, - cid: hostname, - dp: hostname, - dh: appName, - el: appName, - ec: eventCategory - }); - } - }, 1000); - } - - /** - * Request image ping. - * @param {String} url url for ping request - * @param {Object} trackingInfo infos for make query string - * @returns {HTMLElement} - * @memberof tui.util - * @example - * //-- #1. Get Module --// - * var util = require('tui-code-snippet'); // node, commonjs - * var util = tui.util; // distribution file - * - * //-- #2. Use property --// - * util.imagePing('https://www.google-analytics.com/collect', { - * v: 1, - * t: 'event', - * tid: 'trackingid', - * cid: 'cid', - * dp: 'dp', - * dh: 'dh' - * }); - */ - function imagePing(url, trackingInfo) { - var queryString = collection.map(object.keys(trackingInfo), function(key, index) { - var startWith = index === 0 ? '' : '&'; - - return startWith + key + '=' + trackingInfo[key]; - }).join(''); - var trackingElement = document.createElement('img'); - - trackingElement.src = url + '?' + queryString; - - trackingElement.style.display = 'none'; - document.body.appendChild(trackingElement); - document.body.removeChild(trackingElement); - - return trackingElement; - } - - module.exports = { - imagePing: imagePing, - sendHostname: sendHostname - }; - - -/***/ }), -/* 10 */ -/***/ (function(module, exports) { - - /** - * @fileoverview This module detects the kind of well-known browser and version. - * @author NHN. - * FE Development Lab - */ - - 'use strict'; - - /** - * This object has an information that indicate the kind of browser.
    - * The list below is a detectable browser list. - * - ie8 ~ ie11 - * - chrome - * - firefox - * - safari - * - edge - * @memberof tui.util - * @example - * //-- #1. Get Module --// - * var util = require('tui-code-snippet'); // node, commonjs - * var util = tui.util; // distribution file - * - * //-- #2. Use property --// - * util.browser.chrome === true; // chrome - * util.browser.firefox === true; // firefox - * util.browser.safari === true; // safari - * util.browser.msie === true; // IE - * util.browser.edge === true; // edge - * util.browser.others === true; // other browser - * util.browser.version; // browser version - */ - var browser = { - chrome: false, - firefox: false, - safari: false, - msie: false, - edge: false, - others: false, - version: 0 - }; - - if (window && window.navigator) { - detectBrowser(); - } - - /** - * Detect the browser. - * @private - */ - function detectBrowser() { - var nav = window.navigator; - var appName = nav.appName.replace(/\s/g, '_'); - var userAgent = nav.userAgent; - - var rIE = /MSIE\s([0-9]+[.0-9]*)/; - var rIE11 = /Trident.*rv:11\./; - var rEdge = /Edge\/(\d+)\./; - var versionRegex = { - firefox: /Firefox\/(\d+)\./, - chrome: /Chrome\/(\d+)\./, - safari: /Version\/([\d.]+).*Safari\/(\d+)/ - }; - - var key, tmp; - - var detector = { - Microsoft_Internet_Explorer: function() { // eslint-disable-line camelcase - var detectedVersion = userAgent.match(rIE); - - if (detectedVersion) { // ie8 ~ ie10 - browser.msie = true; - browser.version = parseFloat(detectedVersion[1]); - } else { // no version information - browser.others = true; - } - }, - Netscape: function() { // eslint-disable-line complexity - var detected = false; - - if (rIE11.exec(userAgent)) { - browser.msie = true; - browser.version = 11; - detected = true; - } else if (rEdge.exec(userAgent)) { - browser.edge = true; - browser.version = userAgent.match(rEdge)[1]; - detected = true; - } else { - for (key in versionRegex) { - if (versionRegex.hasOwnProperty(key)) { - tmp = userAgent.match(versionRegex[key]); - if (tmp && tmp.length > 1) { // eslint-disable-line max-depth - browser[key] = detected = true; - browser.version = parseFloat(tmp[1] || 0); - break; - } - } - } - } - if (!detected) { - browser.others = true; - } - } - }; - - var fn = detector[appName]; - - if (fn) { - detector[appName](); - } - } - - module.exports = browser; - - -/***/ }), -/* 11 */ -/***/ (function(module, exports, __webpack_require__) { - - /** - * @fileoverview This module has some methods for handling popup-window - * @author NHN. - * FE Development Lab - */ - - 'use strict'; - - var collection = __webpack_require__(4); - var type = __webpack_require__(2); - var func = __webpack_require__(5); - var browser = __webpack_require__(10); - var object = __webpack_require__(1); - - var popupId = 0; - - /** - * Popup management class - * @constructor - * @memberof tui.util - * @example - * // node, commonjs - * var popup = require('tui-code-snippet').popup; - * @example - * // distribution file, script - * - * - * - */ - function CustomEvents() { - /** - * @type {HandlerItem[]} - */ - this.events = null; - - /** - * only for checking specific context event was binded - * @type {object[]} - */ - this.contexts = null; - } - - /** - * Mixin custom events feature to specific constructor - * @param {function} func - constructor - * @example - * //-- #1. Get Module --// - * var CustomEvents = require('tui-code-snippet').CustomEvents; // node, commonjs - * var CustomEvents = tui.util.CustomEvents; // distribution file - * - * //-- #2. Use property --// - * var model; - * function Model() { - * this.name = ''; - * } - * CustomEvents.mixin(Model); - * - * model = new Model(); - * model.on('change', function() { this.name = 'model'; }, this); - * model.fire('change'); - * alert(model.name); // 'model'; - */ - CustomEvents.mixin = function(func) { - object.extend(func.prototype, CustomEvents.prototype); - }; - - /** - * Get HandlerItem object - * @param {function} handler - handler function - * @param {object} [context] - context for handler - * @returns {HandlerItem} HandlerItem object - * @private - */ - CustomEvents.prototype._getHandlerItem = function(handler, context) { - var item = {handler: handler}; - - if (context) { - item.context = context; - } - - return item; - }; - - /** - * Get event object safely - * @param {string} [eventName] - create sub event map if not exist. - * @returns {(object|array)} event object. if you supplied `eventName` - * parameter then make new array and return it - * @private - */ - CustomEvents.prototype._safeEvent = function(eventName) { - var events = this.events; - var byName; - - if (!events) { - events = this.events = {}; - } - - if (eventName) { - byName = events[eventName]; - - if (!byName) { - byName = []; - events[eventName] = byName; - } - - events = byName; - } - - return events; - }; - - /** - * Get context array safely - * @returns {array} context array - * @private - */ - CustomEvents.prototype._safeContext = function() { - var context = this.contexts; - - if (!context) { - context = this.contexts = []; - } - - return context; - }; - - /** - * Get index of context - * @param {object} ctx - context that used for bind custom event - * @returns {number} index of context - * @private - */ - CustomEvents.prototype._indexOfContext = function(ctx) { - var context = this._safeContext(); - var index = 0; - - while (context[index]) { - if (ctx === context[index][0]) { - return index; - } - - index += 1; - } - - return -1; - }; - - /** - * Memorize supplied context for recognize supplied object is context or - * name: handler pair object when off() - * @param {object} ctx - context object to memorize - * @private - */ - CustomEvents.prototype._memorizeContext = function(ctx) { - var context, index; - - if (!type.isExisty(ctx)) { - return; - } - - context = this._safeContext(); - index = this._indexOfContext(ctx); - - if (index > -1) { - context[index][1] += 1; - } else { - context.push([ctx, 1]); - } - }; - - /** - * Forget supplied context object - * @param {object} ctx - context object to forget - * @private - */ - CustomEvents.prototype._forgetContext = function(ctx) { - var context, contextIndex; - - if (!type.isExisty(ctx)) { - return; - } - - context = this._safeContext(); - contextIndex = this._indexOfContext(ctx); - - if (contextIndex > -1) { - context[contextIndex][1] -= 1; - - if (context[contextIndex][1] <= 0) { - context.splice(contextIndex, 1); - } - } - }; - - /** - * Bind event handler - * @param {(string|{name:string, handler:function})} eventName - custom - * event name or an object {eventName: handler} - * @param {(function|object)} [handler] - handler function or context - * @param {object} [context] - context for binding - * @private - */ - CustomEvents.prototype._bindEvent = function(eventName, handler, context) { - var events = this._safeEvent(eventName); - this._memorizeContext(context); - events.push(this._getHandlerItem(handler, context)); - }; - - /** - * Bind event handlers - * @param {(string|{name:string, handler:function})} eventName - custom - * event name or an object {eventName: handler} - * @param {(function|object)} [handler] - handler function or context - * @param {object} [context] - context for binding - * //-- #1. Get Module --// - * var CustomEvents = require('tui-code-snippet').CustomEvents; // node, commonjs - * var CustomEvents = tui.util.CustomEvents; // distribution file - * - * //-- #2. Use property --// - * // # 2.1 Basic Usage - * CustomEvents.on('onload', handler); - * - * // # 2.2 With context - * CustomEvents.on('onload', handler, myObj); - * - * // # 2.3 Bind by object that name, handler pairs - * CustomEvents.on({ - * 'play': handler, - * 'pause': handler2 - * }); - * - * // # 2.4 Bind by object that name, handler pairs with context object - * CustomEvents.on({ - * 'play': handler - * }, myObj); - */ - CustomEvents.prototype.on = function(eventName, handler, context) { - var self = this; - - if (type.isString(eventName)) { - // [syntax 1, 2] - eventName = eventName.split(R_EVENTNAME_SPLIT); - collection.forEach(eventName, function(name) { - self._bindEvent(name, handler, context); - }); - } else if (type.isObject(eventName)) { - // [syntax 3, 4] - context = handler; - collection.forEach(eventName, function(func, name) { - self.on(name, func, context); - }); - } - }; - - /** - * Bind one-shot event handlers - * @param {(string|{name:string,handler:function})} eventName - custom - * event name or an object {eventName: handler} - * @param {function|object} [handler] - handler function or context - * @param {object} [context] - context for binding - */ - CustomEvents.prototype.once = function(eventName, handler, context) { - var self = this; - - if (type.isObject(eventName)) { - context = handler; - collection.forEach(eventName, function(func, name) { - self.once(name, func, context); - }); - - return; - } - - function onceHandler() { // eslint-disable-line require-jsdoc - handler.apply(context, arguments); - self.off(eventName, onceHandler, context); - } - - this.on(eventName, onceHandler, context); - }; - - /** - * Splice supplied array by callback result - * @param {array} arr - array to splice - * @param {function} predicate - function return boolean - * @private - */ - CustomEvents.prototype._spliceMatches = function(arr, predicate) { - var i = 0; - var len; - - if (!type.isArray(arr)) { - return; - } - - for (len = arr.length; i < len; i += 1) { - if (predicate(arr[i]) === true) { - arr.splice(i, 1); - len -= 1; - i -= 1; - } - } - }; - - /** - * Get matcher for unbind specific handler events - * @param {function} handler - handler function - * @returns {function} handler matcher - * @private - */ - CustomEvents.prototype._matchHandler = function(handler) { - var self = this; - - return function(item) { - var needRemove = handler === item.handler; - - if (needRemove) { - self._forgetContext(item.context); - } - - return needRemove; - }; - }; - - /** - * Get matcher for unbind specific context events - * @param {object} context - context - * @returns {function} object matcher - * @private - */ - CustomEvents.prototype._matchContext = function(context) { - var self = this; - - return function(item) { - var needRemove = context === item.context; - - if (needRemove) { - self._forgetContext(item.context); - } - - return needRemove; - }; - }; - - /** - * Get matcher for unbind specific hander, context pair events - * @param {function} handler - handler function - * @param {object} context - context - * @returns {function} handler, context matcher - * @private - */ - CustomEvents.prototype._matchHandlerAndContext = function(handler, context) { - var self = this; - - return function(item) { - var matchHandler = (handler === item.handler); - var matchContext = (context === item.context); - var needRemove = (matchHandler && matchContext); - - if (needRemove) { - self._forgetContext(item.context); - } - - return needRemove; - }; - }; - - /** - * Unbind event by event name - * @param {string} eventName - custom event name to unbind - * @param {function} [handler] - handler function - * @private - */ - CustomEvents.prototype._offByEventName = function(eventName, handler) { - var self = this; - var forEach = collection.forEachArray; - var andByHandler = type.isFunction(handler); - var matchHandler = self._matchHandler(handler); - - eventName = eventName.split(R_EVENTNAME_SPLIT); - - forEach(eventName, function(name) { - var handlerItems = self._safeEvent(name); - - if (andByHandler) { - self._spliceMatches(handlerItems, matchHandler); - } else { - forEach(handlerItems, function(item) { - self._forgetContext(item.context); - }); - - self.events[name] = []; - } - }); - }; - - /** - * Unbind event by handler function - * @param {function} handler - handler function - * @private - */ - CustomEvents.prototype._offByHandler = function(handler) { - var self = this; - var matchHandler = this._matchHandler(handler); - - collection.forEach(this._safeEvent(), function(handlerItems) { - self._spliceMatches(handlerItems, matchHandler); - }); - }; - - /** - * Unbind event by object(name: handler pair object or context object) - * @param {object} obj - context or {name: handler} pair object - * @param {function} handler - handler function - * @private - */ - CustomEvents.prototype._offByObject = function(obj, handler) { - var self = this; - var matchFunc; - - if (this._indexOfContext(obj) < 0) { - collection.forEach(obj, function(func, name) { - self.off(name, func); - }); - } else if (type.isString(handler)) { - matchFunc = this._matchContext(obj); - - self._spliceMatches(this._safeEvent(handler), matchFunc); - } else if (type.isFunction(handler)) { - matchFunc = this._matchHandlerAndContext(handler, obj); - - collection.forEach(this._safeEvent(), function(handlerItems) { - self._spliceMatches(handlerItems, matchFunc); - }); - } else { - matchFunc = this._matchContext(obj); - - collection.forEach(this._safeEvent(), function(handlerItems) { - self._spliceMatches(handlerItems, matchFunc); - }); - } - }; - - /** - * Unbind custom events - * @param {(string|object|function)} eventName - event name or context or - * {name: handler} pair object or handler function - * @param {(function)} handler - handler function - * @example - * //-- #1. Get Module --// - * var CustomEvents = require('tui-code-snippet').CustomEvents; // node, commonjs - * var CustomEvents = tui.util.CustomEvents; // distribution file - * - * //-- #2. Use property --// - * // # 2.1 off by event name - * CustomEvents.off('onload'); - * - * // # 2.2 off by event name and handler - * CustomEvents.off('play', handler); - * - * // # 2.3 off by handler - * CustomEvents.off(handler); - * - * // # 2.4 off by context - * CustomEvents.off(myObj); - * - * // # 2.5 off by context and handler - * CustomEvents.off(myObj, handler); - * - * // # 2.6 off by context and event name - * CustomEvents.off(myObj, 'onload'); - * - * // # 2.7 off by an Object. that is {eventName: handler} - * CustomEvents.off({ - * 'play': handler, - * 'pause': handler2 - * }); - * - * // # 2.8 off the all events - * CustomEvents.off(); - */ - CustomEvents.prototype.off = function(eventName, handler) { - if (type.isString(eventName)) { - // [syntax 1, 2] - this._offByEventName(eventName, handler); - } else if (!arguments.length) { - // [syntax 8] - this.events = {}; - this.contexts = []; - } else if (type.isFunction(eventName)) { - // [syntax 3] - this._offByHandler(eventName); - } else if (type.isObject(eventName)) { - // [syntax 4, 5, 6] - this._offByObject(eventName, handler); - } - }; - - /** - * Fire custom event - * @param {string} eventName - name of custom event - */ - CustomEvents.prototype.fire = function(eventName) { // eslint-disable-line - this.invoke.apply(this, arguments); - }; - - /** - * Fire a event and returns the result of operation 'boolean AND' with all - * listener's results. - * - * So, It is different from {@link CustomEvents#fire}. - * - * In service code, use this as a before event in component level usually - * for notifying that the event is cancelable. - * @param {string} eventName - Custom event name - * @param {...*} data - Data for event - * @returns {boolean} The result of operation 'boolean AND' - * @example - * var map = new Map(); - * map.on({ - * 'beforeZoom': function() { - * // It should cancel the 'zoom' event by some conditions. - * if (that.disabled && this.getState()) { - * return false; - * } - * return true; - * } - * }); - * - * if (this.invoke('beforeZoom')) { // check the result of 'beforeZoom' - * // if true, - * // doSomething - * } - */ - CustomEvents.prototype.invoke = function(eventName) { - var events, args, index, item; - - if (!this.hasListener(eventName)) { - return true; - } - - events = this._safeEvent(eventName); - args = Array.prototype.slice.call(arguments, 1); - index = 0; - - while (events[index]) { - item = events[index]; - - if (item.handler.apply(item.context, args) === false) { - return false; - } - - index += 1; - } - - return true; - }; - - /** - * Return whether at least one of the handlers is registered in the given - * event name. - * @param {string} eventName - Custom event name - * @returns {boolean} Is there at least one handler in event name? - */ - CustomEvents.prototype.hasListener = function(eventName) { - return this.getListenerLength(eventName) > 0; - }; - - /** - * Return a count of events registered. - * @param {string} eventName - Custom event name - * @returns {number} number of event - */ - CustomEvents.prototype.getListenerLength = function(eventName) { - var events = this._safeEvent(eventName); - - return events.length; - }; - - module.exports = CustomEvents; - - -/***/ }), -/* 17 */ -/***/ (function(module, exports, __webpack_require__) { - - /** - * @fileoverview This module provides a Enum Constructor. - * @author NHN. - * FE Development Lab - * @example - * // node, commonjs - * var Enum = require('tui-code-snippet').Enum; - * @example - * // distribution file, script - * - * - * - * - *