{"id":51377209,"url":"https://github.com/edward124689/ngx-email-studio","last_synced_at":"2026-07-05T21:00:33.086Z","repository":{"id":362812525,"uuid":"1257758492","full_name":"edward124689/ngx-email-studio","owner":"edward124689","description":"Angular MJML email builder library for browser-side email template editing and HTML export.","archived":false,"fork":false,"pushed_at":"2026-06-27T02:03:08.000Z","size":9548,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-27T03:11:59.891Z","etag":null,"topics":["angular","angular-library","email-builder","email-template","html-email","mjml","newsletter","tiptap","wysiwyg"],"latest_commit_sha":null,"homepage":"https://edward124689.github.io/ngx-email-studio/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/edward124689.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-03T01:36:00.000Z","updated_at":"2026-06-27T02:02:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/edward124689/ngx-email-studio","commit_stats":null,"previous_names":["edward124689/ngx-email-studio"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/edward124689/ngx-email-studio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edward124689%2Fngx-email-studio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edward124689%2Fngx-email-studio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edward124689%2Fngx-email-studio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edward124689%2Fngx-email-studio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/edward124689","download_url":"https://codeload.github.com/edward124689/ngx-email-studio/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edward124689%2Fngx-email-studio/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35168795,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angular-library","email-builder","email-template","html-email","mjml","newsletter","tiptap","wysiwyg"],"created_at":"2026-07-03T14:00:27.945Z","updated_at":"2026-07-05T21:00:33.080Z","avatar_url":"https://github.com/edward124689.png","language":"TypeScript","funding_links":[],"categories":["Third Party Components"],"sub_categories":["Editors"],"readme":"# ngx-email-studio\n\n[![npm version](https://badge.fury.io/js/ngx-email-studio.svg)](https://www.npmjs.com/package/ngx-email-studio) [![npm downloads](https://img.shields.io/npm/dm/ngx-email-studio.svg)](https://www.npmjs.com/package/ngx-email-studio) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n`ngx-email-studio` is an Angular 21 frontend email builder for composing, importing, editing, previewing, and exporting responsive email templates.\n\nIt provides a polished visual builder shell, MJML import/export for a practical editable subset, clean browser-side HTML export, drag-and-drop content blocks, Tiptap rich text editing, and a responsive preview workflow — all as a standalone Angular component.\n\nLive demo: \u003chttps://edward124689.github.io/ngx-email-studio/\u003e\n\n[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/edward124689/ngx-email-studio/tree/main/examples/stackblitz?file=src%2Fapp%2Fapp.ts)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/edward124689/ngx-email-studio/main/docs/images/email-studio-demo.png\" alt=\"Email Studio visual builder with content modules, email canvas, responsive preview controls, and properties inspector\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\n## Table of Contents\n\n- [Features](#features)\n- [Version Support](#version-support)\n- [Try in StackBlitz](#try-in-stackblitz)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Using an MJML Template](#using-an-mjml-template)\n- [Merge Tags / Data Set](#merge-tags--data-set)\n- [Image Upload Helper](#image-upload-helper)\n- [Text Transform](#text-transform)\n- [Component API](#component-api)\n  - [Inputs](#inputs)\n  - [Outputs](#outputs)\n  - [Configuration](#configuration)\n- [Supported Content Blocks](#supported-content-blocks)\n- [MJML Import and Export](#mjml-import-and-export)\n- [HTML Export](#html-export)\n- [Rich Text Editing](#rich-text-editing)\n- [Document Model](#document-model)\n- [Security Notes](#security-notes)\n- [Development](#development)\n- [Publishing](#publishing)\n- [License](#license)\n\n## Features\n\n- **Angular 21 standalone component**: import `NgxEmailStudio` directly into standalone Angular apps.\n- **Frontend-only builder**: no backend renderer or server-side MJML service required for editing and supported HTML export.\n- **MJML import/export**: import existing MJML templates into an editable document model and export edited content back to MJML.\n- **Clean HTML export**: generate a frontend HTML email export for the supported subset, including email-client friendly tables/resets.\n- **Drag-and-drop layout**: Angular CDK powered content palette, canvas, sections, rows, columns, and nested blocks.\n- **Builder shell**: module library, searchable palette, nested outline, preview size chips, selected-block controls, and tabbed inspector.\n- **Body typography presets**: choose email-safe font-family presets with autocomplete, type a custom sanitized font stack, and set a safe HTTPS font CSS import URL (defaults to Ubuntu).\n- **Tiptap rich text editor**: headings, lists, inline formatting, links, inline images by URL/upload, tables, font size, line height, text alignment, undo/redo, and sanitized source editing.\n- **Merge-tag helper**: pass a `dataSet` of placeholder keys and descriptions so users can search available merge tags and copy keys into the email content.\n- **Image upload helper**: provide `config.uploadImage` so image blocks can pick a local file, preview it, call your upload API, and write the returned URL back into Image URL.\n- **Text Transform**: preview and apply Simplified ↔ Traditional Chinese conversion or whitespace normalization to the whole email.\n- **Responsive preview**: switch between desktop/tablet/mobile/custom preview widths.\n- **Editable social links**: import/export `\u003cmj-social\u003e` with multiple `\u003cmj-social-element\u003e` entries.\n- **Safe import boundaries**: sanitizes rich text, URLs, class/id values, colors, and imported attributes before preview/export.\n- **MIT licensed**.\n\n## Version Support\n\n`ngx-email-studio` follows Angular-major aligned versions.\n\n| ngx-email-studio version | Supported Angular version |\n| --- | --- |\n| `21.x` | Angular `21.x` |\n\nThe first public npm release is `21.0.0`; the current stable release is tracked on the [npm package page](https://www.npmjs.com/package/ngx-email-studio) and in the [GitHub changelog](https://github.com/edward124689/ngx-email-studio/blob/main/CHANGELOG.md).\n\n## Try in StackBlitz\n\nOpen a ready-to-run Angular 21 demo that installs `ngx-email-studio` from npm and shows the builder with MJML seed content, merge tags, Text Transform, and a demo-only image upload hook:\n\n\u003chttps://stackblitz.com/github/edward124689/ngx-email-studio/tree/main/examples/stackblitz?file=src%2Fapp%2Fapp.ts\u003e\n\n## Installation\n\nInstall the package:\n\n```bash\nnpm install ngx-email-studio\n```\n\nInstall Angular and editor peer dependencies if they are not already present in your app:\n\n```bash\nnpm install @angular/core@^21 @angular/common@^21 @angular/forms@^21 @angular/platform-browser@^21 @angular/cdk@^21\nnpm install @tiptap/core@^3 @tiptap/starter-kit@^3 @tiptap/extension-link@^3 @tiptap/extension-image@^3 @tiptap/extension-text-align@^3 @tiptap/extension-text-style@^3 @tiptap/extension-table@^3 @tiptap/extension-table-row@^3 @tiptap/extension-table-cell@^3 @tiptap/extension-table-header@^3\n```\n\n`opencc-js` is a runtime dependency of `ngx-email-studio` and is installed automatically with the package.\n\n## Quick Start\n\nImport the standalone component and render it:\n\n```ts\nimport { Component } from '@angular/core';\nimport { NgxEmailStudio, EmailStudioDataSetItem, EmailStudioResult } from 'ngx-email-studio';\n\n@Component({\n  selector: 'app-email-builder-page',\n  standalone: true,\n  imports: [NgxEmailStudio],\n  template: `\n    \u003cngx-email-studio\n      [mjml]=\"initialMjml\"\n      [showSave]=\"true\"\n      [dataSet]=\"mergeTags\"\n      (change)=\"onChange($event)\"\n      (save)=\"onSave($event)\"\n    /\u003e\n  `,\n})\nexport class EmailBuilderPage {\n  initialMjml = `\n    \u003cmjml\u003e\n      \u003cmj-body\u003e\n        \u003cmj-section\u003e\n          \u003cmj-column\u003e\n            \u003cmj-text\u003e\n              \u003ch1\u003eLaunch a polished campaign in minutes\u003c/h1\u003e\n              \u003cp\u003eCompose responsive emails with reusable content modules.\u003c/p\u003e\n            \u003c/mj-text\u003e\n            \u003cmj-button href=\"https://example.com\"\u003eGet started\u003c/mj-button\u003e\n          \u003c/mj-column\u003e\n        \u003c/mj-section\u003e\n      \u003c/mj-body\u003e\n    \u003c/mjml\u003e\n  `;\n\n  mergeTags: EmailStudioDataSetItem[] = [\n    { key: '{%CLIENT_NAME%}', desc: 'Client name' },\n    { key: '{%ORDER_ID%}', desc: 'Order ID' },\n    { key: '{%DELIVERY_DATE%}', desc: 'Estimated delivery date' },\n    { key: '{%SUPPORT_EMAIL%}', desc: 'Support contact email' },\n  ];\n\n  onChange(result: EmailStudioResult): void {\n    // Emits after builder edits/imports.\n    console.log(result.mjml);\n    console.log(result.html.html);\n  }\n\n  onSave(result: EmailStudioResult): void {\n    // Emits only when the Save button is clicked.\n    console.log(result);\n  }\n}\n```\n\n## Using an MJML Template\n\n`[mjml]` accepts an MJML string and imports it into the editable builder model:\n\n```html\n\u003cngx-email-studio\n  [mjml]=\"campaignMjml\"\n  [previewSize]=\"600\"\n  (change)=\"draft = $event\"\n/\u003e\n```\n\nExample with social links:\n\n```xml\n\u003cmj-social font-size=\"15px\" icon-size=\"30px\" mode=\"horizontal\" padding=\"0\" align=\"center\"\u003e\n  \u003cmj-social-element name=\"facebook\" href=\"https://example.com/facebook\" background-color=\"#A1A0A0\"\u003e\u003c/mj-social-element\u003e\n  \u003cmj-social-element name=\"twitter\" href=\"https://example.com/twitter\" background-color=\"#A1A0A0\"\u003e\u003c/mj-social-element\u003e\n  \u003cmj-social-element name=\"linkedin\" href=\"https://example.com/linkedin\" background-color=\"#A1A0A0\"\u003e\u003c/mj-social-element\u003e\n\u003c/mj-social\u003e\n```\n\nThe editor stores social links as one editable Social block containing multiple icon/name, href, and background color rows, then exports them back to `\u003cmj-social\u003e` / `\u003cmj-social-element\u003e`.\n\n## Merge Tags / Data Set\n\nHost apps can provide a list of merge-tag placeholders with optional descriptions. When the list contains at least one valid key, the builder shows a `Data set` button in the top toolbar before `Import`.\n\n```ts\nimport { EmailStudioDataSetItem } from 'ngx-email-studio';\n\nmergeTags: EmailStudioDataSetItem[] = [\n  { key: '{%CLIENT_NAME%}', desc: 'Client name' },\n  { key: '{%ORDER_ID%}', desc: 'Order ID' },\n  { key: '{%DELIVERY_DATE%}', desc: 'Estimated delivery date' },\n  { key: '{%SUPPORT_EMAIL%}', desc: 'Support contact email' },\n];\n```\n\n```html\n\u003cngx-email-studio\n  [dataSet]=\"mergeTags\"\n  (change)=\"draft = $event\"\n/\u003e\n```\n\nThe modal is a reference helper only: users can search keys/descriptions and copy a key such as `{%CLIENT_NAME%}` into the email content. It does not render, replace, or preview template data.\n\n```ts\nexport interface EmailStudioDataSetItem {\n  key: string;\n  desc?: string;\n}\n```\n\n## Image Upload Helper\n\nImage blocks can show an `Upload image` helper beside the regular `Image URL` field when the host app provides `config.uploadImage`. Tiptap rich-text image insertion reuses the same helper from the `Insert image` modal, so users can either paste a safe image URL or upload a local file and insert the returned URL into rich text. Social links can also use the same helper from each social item's `Upload logo` action to upload a custom icon/logo image for `\u003cmj-social-element src=\"...\"\u003e`. The library handles the file picker, local preview for image blocks, loading/error state, history, and writing the returned URL back to the target image block, rich-text image, or social logo. The host app owns the real upload API, auth, storage provider, and server-side validation.\n\n```ts\nimport { EmailStudioConfig } from 'ngx-email-studio';\n\nconst config: EmailStudioConfig = {\n  uploadImage: async (file, context) =\u003e {\n    const form = new FormData();\n    form.append('file', file);\n    form.append('nodeId', context.nodeId);\n\n    const res = await fetch('/api/email-assets', {\n      method: 'POST',\n      body: form,\n    });\n\n    if (!res.ok) throw new Error('Image upload failed');\n    const data = await res.json();\n\n    return {\n      url: data.url,\n      alt: data.alt,\n    };\n  },\n};\n```\n\n`uploadImage` may return either a string URL or `{ url, alt? }`. If `alt` is returned, it updates the image block alt text. The picker accepts PNG, JPEG, WebP, and GIF files; host apps should still validate uploads server-side. Returned URLs are normalized with the same image URL safety rules used by the editor. When `uploadImage` is omitted, the upload button is hidden and users can still paste an Image URL manually. In `readonly` mode, upload is disabled.\n\n## Text Transform\n\nThe top toolbar includes a `Transform` action for content-level text transformations. It opens a preview modal before applying changes, so users can compare the current text with the transformed result.\n\nSupported actions:\n\n- Simplified Chinese → Traditional Chinese\n- Traditional Chinese → Simplified Chinese\n- Normalize spaces\n\nScope:\n\n- Whole email, covering rich-text blocks and button labels\n\nTransform only changes user-visible text nodes. It preserves rich-text HTML tags and attributes such as links, styles, and classes. Merge-tag placeholders like `{%CLIENT_NAME%}` are preserved unchanged during conversion.\n\nApply participates in the normal document history, so users can undo a transform with the global `Undo` control. In `readonly` mode the Transform action is disabled.\n\nChinese conversion is powered by `opencc-js`, which is declared as a runtime dependency of `ngx-email-studio`. Consumers do not need to install it separately when using npm, pnpm, or yarn.\n\n## Component API\n\n### Inputs\n\n| Input | Type | Description |\n| --- | --- | --- |\n| `mjml` | `string` | Initial MJML source to import into the builder. |\n| `document` | `EmailDocument` | Optional internal JSON document model for apps that persist builder state directly. |\n| `previewSize` | `'desktop' \\| 'tablet' \\| 'mobile' \\| number` | Preview width preset or custom pixel width. |\n| `readonly` | `boolean` | Disables editing controls when true. |\n| `showSave` | `boolean` | Shows or hides the top Save button. Can also be controlled by `config.showSave`. |\n| `dataSet` | `EmailStudioDataSetItem[]` | Optional merge-tag list. When valid keys are provided, shows a searchable `Data set` modal for copying placeholder keys. |\n| `config` | `EmailStudioConfig` | Optional builder configuration. |\n\n### Outputs\n\n| Output | Type | Description |\n| --- | --- | --- |\n| `change` | `EventEmitter\u003cEmailStudioResult\u003e` | Emits after edits/imports. Payload includes MJML and HTML export. |\n| `save` | `EventEmitter\u003cEmailStudioResult\u003e` | Emits when the Save button is clicked. |\n| `mjmlChange` | `EventEmitter\u003cstring\u003e` | MJML-only change output. |\n| `documentChange` | `EventEmitter\u003cEmailDocument\u003e` | Emits the internal JSON document model. |\n| `htmlExport` | `EventEmitter\u003cstring\u003e` | HTML-only export output. |\n| `error` | `EventEmitter\u003cEmailStudioError\u003e` | Emits import/export errors. |\n\n`EmailStudioResult`:\n\n```ts\nexport interface EmailStudioResult {\n  mjml: string;\n  html: {\n    html: string;\n  };\n}\n```\n\n### Configuration\n\n```ts\nimport { EmailStudioConfig } from 'ngx-email-studio';\n\nconfig: EmailStudioConfig = {\n  richTextEditor: 'tiptap',\n  showHtmlPreview: true,\n  showSave: true,\n  title: 'Email Studio',\n  fromLabel: 'hello@example.com',\n  templates: [\n    {\n      icon: 'fa-star', // Font Awesome 4.7 class, or use an image URL\n      name: 'Promo banner',\n      desc: 'Reusable MJML promo section',\n      mjml: '\u003cmj-section\u003e\u003cmj-column\u003e\u003cmj-text\u003ePromo\u003c/mj-text\u003e\u003c/mj-column\u003e\u003c/mj-section\u003e',\n    },\n  ],\n  fontFamilyOptions: [\n    { label: 'Brand Sans', value: '\"Brand Sans\", Arial, sans-serif' },\n  ],\n};\n```\n\n```html\n\u003cngx-email-studio [config]=\"config\" /\u003e\n```\n\n| Config | Type | Default | Description |\n| --- | --- | --- | --- |\n| `richTextEditor` | `'tiptap' \\| 'plain'` | `'tiptap'` | Rich text provider. Use `'plain'` for textarea-only editing. |\n| `showHtmlPreview` | `boolean` | `true` | Enables HTML preview actions in the export modal. |\n| `showSave` | `boolean` | `true` | Shows the Save button. |\n| `templates` | `{ icon?: string; name: string; desc?: string; mjml: string }[]` | — | Host-provided MJML templates shown as draggable Content modules. `icon` accepts a Font Awesome 4.7 class such as `fa-star` or a safe image URL. |\n| `fontFamilyOptions` | `{ label: string; value: string }[]` | Built-in email-safe presets | Extra autocomplete choices for the Body `Email font family` field. Users can still type custom sanitized font stacks. |\n| `title` | `string` | — | Optional builder title text. |\n| `breadcrumb` | `string` | — | Optional breadcrumb/status text for host apps. |\n| `brandLabel` | `string` | — | Optional brand label. |\n| `statusLabel` | `string` | — | Optional status label. |\n| `fromLabel` | `string` | — | Optional campaign sender/from label. |\n\n## Supported Content Blocks\n\nThe `21.x` releases focus on a practical editable MJML subset:\n\n- Body settings\n- Section\n- Row / columns (`\u003cmj-section\u003e` with multiple `\u003cmj-column\u003e` children)\n- Text (`\u003cmj-text\u003e`) with rich HTML content\n- Image (`\u003cmj-image\u003e`)\n- Button (`\u003cmj-button\u003e`)\n- Social links (`\u003cmj-social\u003e` / `\u003cmj-social-element\u003e`)\n- Divider (`\u003cmj-divider\u003e`)\n- Spacer (`\u003cmj-spacer\u003e`)\n\nThe importer also handles common real-template structure such as `\u003cmj-wrapper\u003e` flattening and `\u003cmj-group\u003e` column width calculation where possible.\n\nUnsupported MJML tags are reported in the document `unsupported` list instead of being silently treated as fully editable blocks.\n\n## MJML Import and Export\n\nThe editor uses this flow:\n\n```text\nMJML string\n  -\u003e frontend parser\n  -\u003e EmailDocument JSON model\n  -\u003e visual editor\n  -\u003e MJML export\n  -\u003e HTML export\n```\n\nImport/export is designed for the supported editable subset, not as a full replacement for every MJML feature. For complex templates, unsupported nodes are surfaced so host apps can decide whether to warn users or preserve the original source elsewhere.\n\nNotable import behavior:\n\n- Preserves safe `class` and `id` attributes in rich text.\n- Sanitizes unsafe URLs such as `javascript:` and protocol-relative URLs.\n- Preserves safe rich-text inline styles needed for email templates.\n- Parses wrapper, section, column, image, button, text, divider, spacer, and social content.\n- Keeps social elements editable as a single Social block with multiple items.\n\n## HTML Export\n\n`ngx-email-studio` generates browser-side HTML for the supported subset. The export includes:\n\n- HTML email document shell\n- table-based layout structure\n- reset styles for common email-client behavior\n- responsive column stacking\n- sanitized inline styles and links\n- sandboxed preview inside the builder UI\n\nFor maximum production compatibility with every email client, test exported HTML with your own email QA stack before sending campaigns.\n\n## Rich Text Editing\n\nThe default rich text editor is Tiptap/ProseMirror. It supports:\n\n- paragraph and H1-H6 blocks\n- bold, italic, underline, strike\n- links\n- bullet and ordered lists\n- text alignment\n- font size and line height controls\n- table insertion/editing\n- undo/redo\n- selected-text-block source HTML editing with sanitizer feedback\n\nUse plain mode if you want a lightweight textarea fallback:\n\n```html\n\u003cngx-email-studio [config]=\"{ richTextEditor: 'plain' }\" /\u003e\n```\n\n## Document Model\n\nApps can persist either the exported MJML or the internal JSON model.\n\n```ts\nexport interface EmailDocument {\n  version: string;\n  attrs?: Record\u003cstring, string | number | boolean\u003e;\n  body: EmailNode[];\n  unsupported?: string[];\n}\n\nexport interface EmailNode {\n  id: string;\n  type: 'row' | 'column' | 'section' | 'text' | 'image' | 'button' | 'social' | 'divider' | 'spacer';\n  attrs: Record\u003cstring, string | number | boolean\u003e;\n  children?: EmailNode[];\n}\n```\n\nListen to `(documentChange)` if your application wants to store drafts as structured JSON and rehydrate them later with `[document]`.\n\n## Security Notes\n\nThe builder treats imported MJML and rich text as untrusted input.\n\nCurrent safeguards include:\n\n- removes scripts, iframes, event handlers, and unsupported rich-text attributes;\n- sanitizes link/button/social `href` values;\n- rejects unsafe URL protocols such as `javascript:` and protocol-relative `//example.com`;\n- normalizes safe HTML `class` and `id` values;\n- normalizes colors, sizes, alignments, and selected style attributes before preview/export;\n- uses a sandboxed iframe for exported HTML preview.\n\nStill, email sending is an application responsibility. Validate campaigns, links, and final HTML in your own workflow before production delivery.\n\n## Development\n\n```bash\nnpm install\nnpm run build:lib\nnpm run build:demo\nnpm test -- --watch=false\nnpm run smoke:tiptap\nnpm run pack:lib\n```\n\nRun the demo locally:\n\n```bash\nnpm start\n```\n\nBuild and deploy the GitHub Pages demo:\n\n```bash\nnpm run deploy:pages\n```\n\n## Publishing\n\nBuild and pack the library:\n\n```bash\nnpm run build:lib\nnpm run pack:lib\n```\n\nPublish from the generated library package:\n\n```bash\ncd dist/ngx-email-studio\nnpm publish --access public\n```\n\nThe workspace root is private; the publishable package is `projects/ngx-email-studio` built into `dist/ngx-email-studio`.\n\n## License\n\nMIT © Edward\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedward124689%2Fngx-email-studio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedward124689%2Fngx-email-studio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedward124689%2Fngx-email-studio/lists"}