/** * Insertr Configuration System * Extensible field type detection and form configuration */ class InsertrConfig { constructor(customConfig = {}) { // Default field type mappings this.defaultFieldTypes = { 'H1': { type: 'text', label: 'Headline', maxLength: 60, placeholder: 'Enter headline...' }, 'H2': { type: 'text', label: 'Subheading', maxLength: 80, placeholder: 'Enter subheading...' }, 'H3': { type: 'text', label: 'Section Title', maxLength: 100, placeholder: 'Enter title...' }, 'H4': { type: 'text', label: 'Title', maxLength: 100, placeholder: 'Enter title...' }, 'H5': { type: 'text', label: 'Title', maxLength: 100, placeholder: 'Enter title...' }, 'H6': { type: 'text', label: 'Title', maxLength: 100, placeholder: 'Enter title...' }, 'P': { type: 'textarea', label: 'Paragraph', rows: 3, placeholder: 'Enter paragraph text...' }, 'A': { type: 'link', label: 'Link', placeholder: 'Enter link text...' }, 'SPAN': { type: 'text', label: 'Text', placeholder: 'Enter text...' }, 'CITE': { type: 'text', label: 'Citation', placeholder: 'Enter citation...' }, 'BUTTON': { type: 'text', label: 'Button Text', placeholder: 'Enter button text...' } }; // CSS class-based enhancements this.classEnhancements = { 'lead': { label: 'Lead Paragraph', rows: 4, placeholder: 'Enter lead paragraph...' }, 'btn-primary': { type: 'link', label: 'Primary Button', includeUrl: true, placeholder: 'Enter button text...' }, 'btn-secondary': { type: 'link', label: 'Secondary Button', includeUrl: true, placeholder: 'Enter button text...' }, 'section-subtitle': { label: 'Section Subtitle', placeholder: 'Enter subtitle...' } }; // Content ID-based enhancements this.contentIdRules = [ { pattern: /cta/i, config: { label: 'Call to Action' } }, { pattern: /quote/i, config: { type: 'textarea', rows: 3, label: 'Quote', placeholder: 'Enter quote...' } } ]; // Validation limits this.limits = { maxContentLength: 10000, maxHtmlTags: 20, ...customConfig.limits }; // Markdown configuration this.markdown = { enabled: true, label: 'Content (Markdown)', rows: 8, placeholder: 'Enter content in Markdown format...\n\nUse **bold**, *italic*, [links](url), and double line breaks for new paragraphs.', ...customConfig.markdown }; // Merge custom configurations this.fieldTypes = { ...this.defaultFieldTypes, ...customConfig.fieldTypes }; this.classEnhancements = { ...this.classEnhancements, ...customConfig.classEnhancements }; if (customConfig.contentIdRules) { this.contentIdRules = [...this.contentIdRules, ...customConfig.contentIdRules]; } } /** * Generate field configuration for an element * @param {HTMLElement} element - The element to configure * @returns {Object} Field configuration */ generateFieldConfig(element) { // Check for explicit markdown type first const fieldType = element.getAttribute('data-field-type'); if (fieldType === 'markdown') { return { type: 'markdown', ...this.markdown }; } // Start with tag-based configuration const tagName = element.tagName; let config = { ...this.fieldTypes[tagName] } || { type: 'text', label: 'Content', placeholder: 'Enter content...' }; // Apply class-based enhancements for (const [className, enhancement] of Object.entries(this.classEnhancements)) { if (element.classList.contains(className)) { config = { ...config, ...enhancement }; } } // Apply content ID-based rules const contentId = element.getAttribute('data-content-id'); if (contentId) { for (const rule of this.contentIdRules) { if (rule.pattern.test(contentId)) { config = { ...config, ...rule.config }; } } } return config; } /** * Add or override field type mapping * @param {string} tagName - HTML tag name * @param {Object} config - Field configuration */ addFieldType(tagName, config) { this.fieldTypes[tagName.toUpperCase()] = config; } /** * Add class-based enhancement * @param {string} className - CSS class name * @param {Object} enhancement - Configuration enhancement */ addClassEnhancement(className, enhancement) { this.classEnhancements[className] = enhancement; } /** * Add content ID rule * @param {RegExp|string} pattern - Pattern to match content IDs * @param {Object} config - Configuration to apply */ addContentIdRule(pattern, config) { const regexPattern = pattern instanceof RegExp ? pattern : new RegExp(pattern, 'i'); this.contentIdRules.push({ pattern: regexPattern, config }); } /** * Get validation limits * @returns {Object} Validation limits */ getValidationLimits() { return { ...this.limits }; } } // Export for module usage if (typeof module !== 'undefined' && module.exports) { module.exports = InsertrConfig; } // Global export for browser usage if (typeof window !== 'undefined') { window.InsertrConfig = InsertrConfig; }