cms-block-editor 1.0.16 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,6 +19,7 @@ A powerful, feature-rich block editor for CMS applications built with Lexical an
19
19
  📊 **Tables** - Visual table builder with configurable rows/columns and professional styling
20
20
  🎨 **Styling** - Background colors, images, gradients, opacity controls
21
21
  🌈 **Themes** - 10 preset themes with light/dark mode and custom theme support
22
+ 🔍 **SEO Tools** - Complete SEO optimization with meta tags, structured data, and analysis
22
23
  📱 **Responsive** - Mobile-first design with automatic responsive behavior
23
24
  💾 **Export/Import** - HTML and Markdown support
24
25
  🎯 **Section Editor** - Full control over section layout, spacing, and styling
@@ -79,6 +80,9 @@ Main editor component with full editing capabilities.
79
80
  - `onImageAdded?: (file: File) => Promise<string>` - Custom image upload handler that returns the image URL
80
81
  - `onVideoAdded?: (file: File) => Promise<string>` - Custom video upload handler that returns the video URL
81
82
  - `useBase64Url?: boolean` - Use base64 encoding for images (default: `true`)
83
+ - `seoMetadata?: SEOMetadata` - SEO metadata for the content
84
+ - `onSEOMetadataChange?: (metadata: SEOMetadata) => void` - Callback when SEO metadata changes
85
+ - `showSEO?: boolean` - Show/hide SEO button (default: `true`)
82
86
 
83
87
  ### CMSRenderer
84
88
 
@@ -310,6 +314,59 @@ importFromHTML(editor, '<h1>Hello World</h1>');
310
314
  importFromMarkdown(editor, '# Hello World');
311
315
  ```
312
316
 
317
+ ### SEO Optimization
318
+
319
+ Manage SEO metadata and analyze content:
320
+
321
+ ```typescript
322
+ import { CMSBlockEditor, SEOMetadata } from 'cms-block-editor';
323
+ import { useState } from 'react';
324
+
325
+ function Editor() {
326
+ const [content, setContent] = useState('');
327
+ const [seoMetadata, setSeoMetadata] = useState<SEOMetadata>({
328
+ title: 'My Page Title',
329
+ description: 'My page description for search engines',
330
+ keywords: ['keyword1', 'keyword2', 'keyword3'],
331
+ ogImage: 'https://example.com/image.jpg',
332
+ twitterCard: 'summary_large_image',
333
+ });
334
+
335
+ return (
336
+ <CMSBlockEditor
337
+ value={content}
338
+ onChange={setContent}
339
+ seoMetadata={seoMetadata}
340
+ onSEOMetadataChange={setSeoMetadata}
341
+ showSEO={true}
342
+ />
343
+ );
344
+ }
345
+ ```
346
+
347
+ **SEO Features**:
348
+ - Meta tags (title, description, keywords, author, canonical)
349
+ - Open Graph tags for social media
350
+ - Twitter Card support
351
+ - Article metadata
352
+ - Schema.org structured data
353
+ - Real-time SEO analysis with scoring
354
+ - Keyword extraction
355
+ - Slug generation
356
+
357
+ **Programmatic SEO Analysis**:
358
+ ```typescript
359
+ import { analyzeSEO, generateMetaTags } from 'cms-block-editor';
360
+
361
+ // Analyze content
362
+ const analysis = analyzeSEO(htmlContent, metadata);
363
+ console.log('SEO Score:', analysis.score); // 0-100
364
+
365
+ // Generate meta tags
366
+ const metaTags = generateMetaTags(metadata);
367
+ // Returns HTML string with all meta tags
368
+ ```
369
+
313
370
  ## Styling
314
371
 
315
372
  The editor comes with default styles. Import the CSS file:
@@ -373,7 +430,9 @@ Check out the [example app](./example-app) for a complete implementation with:
373
430
 
374
431
  Comprehensive guides available:
375
432
  - [Features Summary](./docs/FEATURES-SUMMARY.md) - Complete overview of all features
433
+ - [SEO Optimization Guide](./docs/SEO-GUIDE.md) - Complete SEO tools and best practices
376
434
  - [Theme System Guide](./docs/THEME-GUIDE.md) - Complete theming and customization
435
+ - [Advanced Theming Guide](./docs/ADVANCED-THEMING-GUIDE.md) - Theme customizer and builder API
377
436
  - [Video Upload Guide](./docs/VIDEO-GUIDE.md) - Native HTML5 video upload and playback
378
437
  - [Image Editing Guide](./docs/IMAGE-EDITING-GUIDE.md) - Advanced image filters and effects
379
438
  - [Section Creator Guide](./SECTION-CREATOR-GUIDE.md)
package/dist/index.css CHANGED
@@ -77,6 +77,13 @@
77
77
  transform: none;
78
78
  box-shadow: none;
79
79
  }
80
+ .cms-toolbar-seo {
81
+ padding: 0.5rem 1rem;
82
+ border-bottom: 1px solid var(--cms-color-border, #e5e7eb);
83
+ background: var(--cms-color-surface, #f9fafb);
84
+ display: flex;
85
+ justify-content: flex-end;
86
+ }
80
87
  .cms-editor-content {
81
88
  min-height: 300px;
82
89
  max-height: 600px;
@@ -4313,4 +4320,380 @@
4313
4320
  width: 100%;
4314
4321
  }
4315
4322
  }
4323
+
4324
+ /* src/styles/seo.css */
4325
+ .cms-seo-trigger {
4326
+ padding: 0.5rem 1rem;
4327
+ background: var(--cms-color-primary, #667eea);
4328
+ color: white;
4329
+ border: none;
4330
+ border-radius: 6px;
4331
+ font-size: 0.875rem;
4332
+ font-weight: 600;
4333
+ cursor: pointer;
4334
+ transition: all 0.2s;
4335
+ }
4336
+ .cms-seo-trigger:hover {
4337
+ background: var(--cms-color-primary-hover, #5568d3);
4338
+ transform: translateY(-1px);
4339
+ }
4340
+ .cms-seo-panel {
4341
+ position: fixed;
4342
+ top: 0;
4343
+ left: 0;
4344
+ right: 0;
4345
+ bottom: 0;
4346
+ z-index: 9999;
4347
+ display: flex;
4348
+ align-items: center;
4349
+ justify-content: center;
4350
+ }
4351
+ .cms-seo-overlay {
4352
+ position: absolute;
4353
+ top: 0;
4354
+ left: 0;
4355
+ right: 0;
4356
+ bottom: 0;
4357
+ background: rgba(0, 0, 0, 0.5);
4358
+ backdrop-filter: blur(4px);
4359
+ }
4360
+ .cms-seo-content {
4361
+ position: relative;
4362
+ background: var(--cms-color-background, #ffffff);
4363
+ width: 700px;
4364
+ max-width: 95vw;
4365
+ max-height: 90vh;
4366
+ border-radius: 12px;
4367
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
4368
+ display: flex;
4369
+ flex-direction: column;
4370
+ animation: slideUp 0.3s ease-out;
4371
+ }
4372
+ @keyframes slideUp {
4373
+ from {
4374
+ opacity: 0;
4375
+ transform: translateY(20px);
4376
+ }
4377
+ to {
4378
+ opacity: 1;
4379
+ transform: translateY(0);
4380
+ }
4381
+ }
4382
+ .cms-seo-header {
4383
+ display: flex;
4384
+ justify-content: space-between;
4385
+ align-items: center;
4386
+ padding: 1.5rem;
4387
+ border-bottom: 1px solid var(--cms-color-border, #e5e7eb);
4388
+ }
4389
+ .cms-seo-header h2 {
4390
+ margin: 0;
4391
+ font-size: 1.5rem;
4392
+ font-weight: 700;
4393
+ color: var(--cms-color-text-primary, #1f2937);
4394
+ }
4395
+ .cms-seo-close {
4396
+ width: 36px;
4397
+ height: 36px;
4398
+ display: flex;
4399
+ align-items: center;
4400
+ justify-content: center;
4401
+ background: none;
4402
+ border: none;
4403
+ font-size: 2rem;
4404
+ color: var(--cms-color-text-secondary, #6b7280);
4405
+ cursor: pointer;
4406
+ border-radius: 6px;
4407
+ transition: all 0.2s;
4408
+ }
4409
+ .cms-seo-close:hover {
4410
+ background: var(--cms-color-error-light, #fee2e2);
4411
+ color: var(--cms-color-error, #ef4444);
4412
+ }
4413
+ .cms-seo-tabs {
4414
+ display: flex;
4415
+ border-bottom: 1px solid var(--cms-color-border, #e5e7eb);
4416
+ background: var(--cms-color-surface, #f9fafb);
4417
+ }
4418
+ .cms-seo-tabs button {
4419
+ flex: 1;
4420
+ padding: 1rem;
4421
+ background: none;
4422
+ border: none;
4423
+ border-bottom: 2px solid transparent;
4424
+ font-size: 0.875rem;
4425
+ font-weight: 600;
4426
+ color: var(--cms-color-text-secondary, #6b7280);
4427
+ cursor: pointer;
4428
+ transition: all 0.2s;
4429
+ }
4430
+ .cms-seo-tabs button:hover {
4431
+ background: var(--cms-color-surface-hover, #f3f4f6);
4432
+ color: var(--cms-color-text-primary, #1f2937);
4433
+ }
4434
+ .cms-seo-tabs button.active {
4435
+ color: var(--cms-color-primary, #667eea);
4436
+ border-bottom-color: var(--cms-color-primary, #667eea);
4437
+ background: var(--cms-color-background, #ffffff);
4438
+ }
4439
+ .cms-seo-body {
4440
+ flex: 1;
4441
+ overflow-y: auto;
4442
+ padding: 1.5rem;
4443
+ }
4444
+ .cms-seo-tab {
4445
+ display: flex;
4446
+ flex-direction: column;
4447
+ gap: 1rem;
4448
+ }
4449
+ .cms-seo-tab h3 {
4450
+ margin: 1rem 0 0.5rem 0;
4451
+ font-size: 1rem;
4452
+ font-weight: 600;
4453
+ color: var(--cms-color-text-primary, #1f2937);
4454
+ }
4455
+ .cms-seo-tab h3:first-child {
4456
+ margin-top: 0;
4457
+ }
4458
+ .cms-seo-field {
4459
+ display: flex;
4460
+ flex-direction: column;
4461
+ gap: 0.5rem;
4462
+ }
4463
+ .cms-seo-field label {
4464
+ font-size: 0.875rem;
4465
+ font-weight: 500;
4466
+ color: var(--cms-color-text-primary, #1f2937);
4467
+ display: flex;
4468
+ justify-content: space-between;
4469
+ align-items: center;
4470
+ }
4471
+ .cms-char-count {
4472
+ font-size: 0.75rem;
4473
+ color: var(--cms-color-text-tertiary, #9ca3af);
4474
+ font-weight: 400;
4475
+ }
4476
+ .cms-seo-field input,
4477
+ .cms-seo-field textarea,
4478
+ .cms-seo-field select {
4479
+ padding: 0.75rem;
4480
+ background: var(--cms-color-surface, #f9fafb);
4481
+ border: 1px solid var(--cms-color-border, #e5e7eb);
4482
+ border-radius: 6px;
4483
+ font-size: 0.875rem;
4484
+ color: var(--cms-color-text-primary, #1f2937);
4485
+ font-family: inherit;
4486
+ transition: all 0.2s;
4487
+ }
4488
+ .cms-seo-field input:focus,
4489
+ .cms-seo-field textarea:focus,
4490
+ .cms-seo-field select:focus {
4491
+ outline: none;
4492
+ border-color: var(--cms-color-primary, #667eea);
4493
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
4494
+ }
4495
+ .cms-seo-field textarea {
4496
+ resize: vertical;
4497
+ min-height: 60px;
4498
+ }
4499
+ .cms-seo-field-with-action {
4500
+ display: flex;
4501
+ gap: 0.5rem;
4502
+ }
4503
+ .cms-seo-field-with-action input {
4504
+ flex: 1;
4505
+ }
4506
+ .cms-btn-icon {
4507
+ width: 40px;
4508
+ height: 40px;
4509
+ display: flex;
4510
+ align-items: center;
4511
+ justify-content: center;
4512
+ background: var(--cms-color-surface, #f3f4f6);
4513
+ border: 1px solid var(--cms-color-border, #e5e7eb);
4514
+ border-radius: 6px;
4515
+ font-size: 1.25rem;
4516
+ cursor: pointer;
4517
+ transition: all 0.2s;
4518
+ }
4519
+ .cms-btn-icon:hover {
4520
+ background: var(--cms-color-primary, #667eea);
4521
+ border-color: var(--cms-color-primary, #667eea);
4522
+ transform: scale(1.05);
4523
+ }
4524
+ .cms-seo-validation-errors {
4525
+ padding: 1rem;
4526
+ background: var(--cms-color-error-light, #fee2e2);
4527
+ border: 1px solid var(--cms-color-error, #ef4444);
4528
+ border-radius: 6px;
4529
+ font-size: 0.875rem;
4530
+ color: var(--cms-color-error-dark, #991b1b);
4531
+ }
4532
+ .cms-seo-validation-errors ul {
4533
+ margin: 0.5rem 0 0 0;
4534
+ padding-left: 1.5rem;
4535
+ }
4536
+ .cms-seo-info {
4537
+ padding: 1rem;
4538
+ background: var(--cms-color-info-light, #dbeafe);
4539
+ border: 1px solid var(--cms-color-info, #3b82f6);
4540
+ border-radius: 6px;
4541
+ font-size: 0.875rem;
4542
+ color: var(--cms-color-info-dark, #1e40af);
4543
+ }
4544
+ .cms-seo-analysis-empty {
4545
+ display: flex;
4546
+ flex-direction: column;
4547
+ align-items: center;
4548
+ justify-content: center;
4549
+ gap: 1rem;
4550
+ padding: 3rem 1.5rem;
4551
+ text-align: center;
4552
+ color: var(--cms-color-text-secondary, #6b7280);
4553
+ }
4554
+ .cms-seo-score {
4555
+ display: flex;
4556
+ flex-direction: column;
4557
+ align-items: center;
4558
+ gap: 1rem;
4559
+ padding: 2rem;
4560
+ border: 3px solid;
4561
+ border-radius: 12px;
4562
+ margin-bottom: 1rem;
4563
+ }
4564
+ .cms-seo-score-circle {
4565
+ width: 100px;
4566
+ height: 100px;
4567
+ border-radius: 50%;
4568
+ display: flex;
4569
+ align-items: center;
4570
+ justify-content: center;
4571
+ font-size: 2.5rem;
4572
+ font-weight: 700;
4573
+ color: white;
4574
+ }
4575
+ .cms-seo-score-label {
4576
+ font-size: 1.25rem;
4577
+ font-weight: 600;
4578
+ color: var(--cms-color-text-primary, #1f2937);
4579
+ }
4580
+ .cms-seo-issues,
4581
+ .cms-seo-suggestions {
4582
+ margin-bottom: 1.5rem;
4583
+ }
4584
+ .cms-seo-issues h3,
4585
+ .cms-seo-suggestions h3,
4586
+ .cms-seo-metrics h3 {
4587
+ margin: 0 0 1rem 0;
4588
+ font-size: 1rem;
4589
+ font-weight: 600;
4590
+ color: var(--cms-color-text-primary, #1f2937);
4591
+ }
4592
+ .cms-seo-issue,
4593
+ .cms-seo-suggestion {
4594
+ display: flex;
4595
+ gap: 0.75rem;
4596
+ padding: 1rem;
4597
+ background: var(--cms-color-surface, #f9fafb);
4598
+ border-radius: 6px;
4599
+ margin-bottom: 0.5rem;
4600
+ }
4601
+ .cms-seo-issue-error {
4602
+ background: var(--cms-color-error-light, #fee2e2);
4603
+ border-left: 3px solid var(--cms-color-error, #ef4444);
4604
+ }
4605
+ .cms-seo-issue-warning {
4606
+ background: var(--cms-color-warning-light, #fef3c7);
4607
+ border-left: 3px solid var(--cms-color-warning, #f59e0b);
4608
+ }
4609
+ .cms-seo-issue-icon,
4610
+ .cms-seo-suggestion-icon {
4611
+ font-size: 1.25rem;
4612
+ flex-shrink: 0;
4613
+ }
4614
+ .cms-seo-issue-message,
4615
+ .cms-seo-suggestion-message {
4616
+ font-size: 0.875rem;
4617
+ font-weight: 500;
4618
+ color: var(--cms-color-text-primary, #1f2937);
4619
+ margin-bottom: 0.25rem;
4620
+ }
4621
+ .cms-seo-issue-meta,
4622
+ .cms-seo-suggestion-meta {
4623
+ font-size: 0.75rem;
4624
+ color: var(--cms-color-text-tertiary, #9ca3af);
4625
+ text-transform: capitalize;
4626
+ }
4627
+ .cms-seo-metrics-grid {
4628
+ display: grid;
4629
+ grid-template-columns: repeat(3, 1fr);
4630
+ gap: 1rem;
4631
+ }
4632
+ .cms-seo-metric {
4633
+ padding: 1rem;
4634
+ background: var(--cms-color-surface, #f9fafb);
4635
+ border: 1px solid var(--cms-color-border, #e5e7eb);
4636
+ border-radius: 8px;
4637
+ text-align: center;
4638
+ }
4639
+ .cms-seo-metric-value {
4640
+ font-size: 1.5rem;
4641
+ font-weight: 700;
4642
+ color: var(--cms-color-primary, #667eea);
4643
+ margin-bottom: 0.25rem;
4644
+ }
4645
+ .cms-seo-metric-label {
4646
+ font-size: 0.75rem;
4647
+ color: var(--cms-color-text-secondary, #6b7280);
4648
+ text-transform: uppercase;
4649
+ letter-spacing: 0.5px;
4650
+ }
4651
+ .cms-seo-footer {
4652
+ display: flex;
4653
+ justify-content: flex-end;
4654
+ gap: 0.75rem;
4655
+ padding: 1.5rem;
4656
+ border-top: 1px solid var(--cms-color-border, #e5e7eb);
4657
+ background: var(--cms-color-surface, #f9fafb);
4658
+ }
4659
+ .cms-btn-secondary,
4660
+ .cms-btn-primary {
4661
+ padding: 0.75rem 1.5rem;
4662
+ border: none;
4663
+ border-radius: 6px;
4664
+ font-size: 0.875rem;
4665
+ font-weight: 600;
4666
+ cursor: pointer;
4667
+ transition: all 0.2s;
4668
+ }
4669
+ .cms-btn-secondary {
4670
+ background: var(--cms-color-surface, #f3f4f6);
4671
+ color: var(--cms-color-text-primary, #1f2937);
4672
+ border: 1px solid var(--cms-color-border, #e5e7eb);
4673
+ }
4674
+ .cms-btn-secondary:hover {
4675
+ background: var(--cms-color-surface-hover, #e5e7eb);
4676
+ }
4677
+ .cms-btn-primary {
4678
+ background: var(--cms-color-primary, #667eea);
4679
+ color: white;
4680
+ }
4681
+ .cms-btn-primary:hover {
4682
+ background: var(--cms-color-primary-hover, #5568d3);
4683
+ transform: translateY(-1px);
4684
+ }
4685
+ @media (max-width: 768px) {
4686
+ .cms-seo-content {
4687
+ width: 100vw;
4688
+ max-height: 100vh;
4689
+ border-radius: 0;
4690
+ }
4691
+ .cms-seo-metrics-grid {
4692
+ grid-template-columns: repeat(2, 1fr);
4693
+ }
4694
+ .cms-seo-tabs button {
4695
+ font-size: 0.75rem;
4696
+ padding: 0.75rem 0.5rem;
4697
+ }
4698
+ }
4316
4699
  /*# sourceMappingURL=index.css.map */