(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/compiler'), require('@wm/core'), require('lodash-es')) :
    typeof define === 'function' && define.amd ? define(['exports', '@angular/compiler', '@wm/core', 'lodash-es'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.wm = global.wm || {}, global.wm.transpiler = {}), global.ng.compiler, global.wm.core, global._));
})(this, (function (exports, compiler, core, lodashEs) { 'use strict';

    const NG_FORM_MODULE = [{ from: '@angular/forms', name: 'FormsModule', as: 'ngFormsModule' }];
    const NG_REACTIVE_FORM_MODULE = [{ from: '@angular/forms', name: 'ReactiveFormsModule', as: 'ngReactiveFormsModule' }];
    const NGX_BS_DATE_PICKER = [{ from: 'ngx-bootstrap/datepicker', name: 'BsDatepickerModule', as: 'ngx_BsDatepickerModule' }];
    const NGX_CAROUSEL_MODULE = [{ from: 'ngx-bootstrap/carousel', name: 'CarouselModule', as: 'ngxCarouselModule', forRoot: true }];
    const NGX_COLOR_PICKER_MODULE = [{ from: 'ngx-color-picker', name: 'ColorPickerModule', as: 'ngx_ColorPickerModule' }];
    const NGX_DROP_DOWN_MODULE = [{ from: 'ngx-bootstrap/dropdown', name: 'BsDropdownModule', as: 'ngxBsDropdownModule', forRoot: true }];
    const NGX_MODAL_MODULE = [{ from: 'ngx-bootstrap/modal', name: 'ModalModule', as: 'ngx_ModalModule' }];
    const NGX_PAGINATION_MODULE = [{ from: 'ngx-bootstrap/pagination', name: 'PaginationModule', as: 'ngxPaginationModule', forRoot: true }];
    const NGX_POPOVER_MODULE = [{ from: 'ngx-bootstrap/popover', name: 'PopoverModule', as: 'ngxPopoverModule', forRoot: true }];
    const NGX_TIME_PICKER = [{ from: 'ngx-bootstrap/timepicker', name: 'TimepickerModule', as: 'ngx_TimepickerModule', forRoot: true }];
    const NGX_TOOL_TIP_MODULE = [{ from: 'ngx-bootstrap/tooltip', name: 'TooltipModule', as: 'ngxTooltipModule', forRoot: true }];
    const NGX_TYPE_HEAD_MODULE = [{ from: 'ngx-bootstrap/typeahead', name: 'TypeaheadModule', as: 'ngxTypeaheadModule', forRoot: true }];
    const PROGRESS_MODULE = [{ from: '@wm/components/basic/progress', name: 'ProgressModule' }];
    const MOBILE_BASIC_MODULE = [...PROGRESS_MODULE, { from: '@wm/mobile/components/basic', name: 'BasicModule', as: 'WM_MobileBasicModule', platformType: 'MOBILE' }];
    const MOBILE_FILE_UPLOAD_MODULE = [{ from: '@wm/mobile/components/input/file-upload', name: 'FileUploadModule', as: 'WM_MobileFileUploadModule', platformType: 'MOBILE' }];
    const PAGE_MODULE = [{ from: '@wm/components/page', name: 'PageModule' },
        { from: '@wm/mobile/components/page', name: 'PageModule', as: 'WM_MobilePageModule', platformType: 'MOBILE' }];
    const BASIC_MODULE = [{ from: '@wm/components/basic', name: 'BasicModule' }, ...MOBILE_BASIC_MODULE];
    const INPUT_MODULE = [...NG_FORM_MODULE, { from: '@wm/components/input', name: 'InputModule' }];
    const DIALOG_MODULE = [...NGX_MODAL_MODULE, ...INPUT_MODULE, { from: '@wm/components/dialogs', name: 'DialogModule' }];
    const PAGINATION_MODULE = [...NG_FORM_MODULE, ...NGX_PAGINATION_MODULE, { from: '@wm/components/data/pagination', name: 'PaginationModule' }];
    const SEARCH_MODULE = [...NG_FORM_MODULE, ...NGX_TYPE_HEAD_MODULE, { from: '@wm/components/basic/search', name: 'SearchModule' }];
    const ACCORDION_MODULE = [{ from: '@wm/components/containers/accordion', name: 'AccordionModule' }];
    const LINEAR_LAYOUT_MODULE = [{ from: '@wm/components/containers/linear-layout', name: 'LinearLayoutModule' }];
    const ALERT_DIALOG_MODULE = [...DIALOG_MODULE, { from: '@wm/components/dialogs/alert-dialog', name: 'AlertDialogModule' }];
    const BARCODE_SCANNER_MODULE = [{ from: '@wm/mobile/components/device/barcode-scanner', name: 'BarcodeScannerModule' }];
    const MENU_MODULE = [...BASIC_MODULE, ...NGX_DROP_DOWN_MODULE, ...INPUT_MODULE, { from: '@wm/components/navigation/menu', name: 'MenuModule' }];
    const BREAD_CRUMB_MODULE = [...MENU_MODULE, { from: '@wm/components/navigation/breadcrumb', name: 'BreadcrumbModule' }];
    const CAMERA_MODULE = [{ from: '@wm/mobile/components/device/camera', name: 'CameraModule' }];
    const CALENDAR_MODULE = [...NG_FORM_MODULE, ...NGX_BS_DATE_PICKER, { from: '@wm/components/input/calendar', name: 'CalendarModule' }];
    const CAROUSEL_MODULE = [...NGX_CAROUSEL_MODULE, { from: '@wm/components/advanced/carousel', name: 'CarouselModule' }];
    const CHART_MODULE = [...BASIC_MODULE, { from: '@wm/components/chart', name: 'ChartModule' }];
    const CHIPS_MODULE = [...SEARCH_MODULE, { from: '@wm/components/input/chips', name: 'ChipsModule' }];
    const COLOR_PICKER_MODULE = [...NG_FORM_MODULE, ...NGX_COLOR_PICKER_MODULE, { from: '@wm/components/input/color-picker', name: 'ColorPickerModule' }];
    const CONFIRM_DIALOG_MODULE = [...DIALOG_MODULE, { from: '@wm/components/dialogs/confirm-dialog', name: 'ConfirmDialogModule' }];
    const CONTENT_MODULE = [{ from: '@wm/components/page', name: 'PageModule' }];
    const CURRENCY_MODULE = [...INPUT_MODULE, { from: '@wm/components/input/currency', name: 'CurrencyModule' }];
    const DESIGN_DIALOG_MODULE = [...DIALOG_MODULE, { from: '@wm/components/dialogs/design-dialog', name: 'DesignDialogModule' }];
    const EPOCH_MODULE = [...NG_FORM_MODULE, ...NGX_BS_DATE_PICKER, ...NGX_TIME_PICKER, ...NGX_DROP_DOWN_MODULE, { from: '@wm/components/input/epoch', name: 'EpochModule' }];
    const FILE_UPLOAD_MODULE = [...MOBILE_FILE_UPLOAD_MODULE, { from: '@wm/components/input/file-upload', name: 'FileUploadModule' }];
    const FOOTER_MODULE = [{ from: '@wm/components/page/footer', name: 'FooterModule' }];
    const HEADER_MODULE = [{ from: '@wm/components/page/header', name: 'HeaderModule' }];
    const IFRAME_DIALOG_MODULE = [...BASIC_MODULE, ...DIALOG_MODULE, { from: '@wm/components/dialogs/iframe-dialog', name: 'IframeDialogModule' }];
    const LAYOUT_GRID_MODULE = [{ from: '@wm/components/containers/layout-grid', name: 'LayoutGridModule' }];
    const LOGIN_DIALOG_MODULE = [...DIALOG_MODULE, { from: '@wm/components/dialogs/login-dialog', name: 'LoginDialogModule' }];
    const CARD_MODULE = [...NGX_DROP_DOWN_MODULE, ...MENU_MODULE, ...BASIC_MODULE, { from: '@wm/components/data/card', name: 'CardModule' }];
    const MARQUEE_MODULE = [{ from: '@wm/components/advanced/marquee', name: 'MarqueeModule' }];
    const LEFT_PANEL_MODULE = [{ from: '@wm/components/page/left-panel', name: 'LeftPanelModule' },
        { from: '@wm/mobile/components/page/left-panel', name: 'LeftPanelModule', as: 'WM_MobileLeftPanelModule', platformType: 'MOBILE' }];
    const LIST_MODULE = [...PAGINATION_MODULE, ...INPUT_MODULE, { from: '@wm/components/data/list', name: 'ListModule' }];
    const LOGIN_MODULE = [{ from: '@wm/components/advanced/login', name: 'LoginModule' }];
    const MOBILE_NAV_BAR_MODULE = [...LEFT_PANEL_MODULE, ...SEARCH_MODULE, ...PAGE_MODULE, { from: '@wm/mobile/components/page/mobile-navbar', name: 'MobileNavbarModule' }];
    const MEDIA_LIST_MODULE = [...BASIC_MODULE, ...PAGE_MODULE, ...MOBILE_NAV_BAR_MODULE, { from: '@wm/mobile/components/data/media-list', name: 'MediaListModule' }];
    const MOBILE_TAB_BAR_MODULE = [{ from: '@wm/mobile/components/page/tab-bar', name: 'TabBarModule' }];
    const NAVBAR_MODULE = [{ from: '@wm/components/navigation/navbar', name: 'NavbarModule' }];
    const POPOVER_MODULE = [...NGX_POPOVER_MODULE, ...BASIC_MODULE, { from: '@wm/components/navigation/popover', name: 'PopoverModule' }];
    const PANEL_MODULE = [...MENU_MODULE, { from: '@wm/components/containers/panel', name: 'PanelModule' }];
    const PARTIAL_DIALOG_MODULE = [...DIALOG_MODULE, { from: '@wm/components/dialogs/partial-dialog', name: 'PartialDialogModule' }];
    const PREFAB_MODULE = [{ from: '@wm/components/prefab', name: 'PrefabModule' }];
    const RATING_MODULE = [{ from: '@wm/components/input/rating', name: 'RatingModule' }];
    const RICH_TEXT_EDITOR_MODULE = [{ from: '@wm/components/basic/rich-text-editor', name: 'RichTextEditorModule' }];
    const RIGHT_PANEL_MODULE = [{ from: '@wm/components/page/right-panel', name: 'RightPanelModule' }];
    const SEGMENTED_CONTROL_MODULE = [{ from: '@wm/mobile/components/containers/segmented-control', name: 'SegmentedControlModule' }];
    const SLIDER_MODULE = [...NG_FORM_MODULE, { from: '@wm/components/input/slider', name: 'SliderModule' }];
    const TABS_MODULE = [{ from: '@wm/components/containers/tabs', name: 'TabsModule' }];
    const TABLE_MODULE = [...NG_FORM_MODULE, ...NG_REACTIVE_FORM_MODULE, ...PAGINATION_MODULE, ...MENU_MODULE, ...BASIC_MODULE, ...INPUT_MODULE, ...NGX_TOOL_TIP_MODULE, ...LIST_MODULE, { from: '@wm/components/data/table', name: 'TableModule' }];
    const TILE_MODULE = [{ from: '@wm/components/containers/tile', name: 'TileModule' }];
    const TOP_NAV_MODULE = [{ from: '@wm/components/page/top-nav', name: 'TopNavModule' }];
    const TREE_MODULE = [{ from: '@wm/components/basic/tree', name: 'TreeModule' }];
    const WIZARD_MODULE = [...NG_FORM_MODULE, { from: '@wm/components/containers/wizard', name: 'WizardModule' }];
    const LIVE_TABLE_MODULE = [...TABLE_MODULE, { from: '@wm/components/data/live-table', name: 'LiveTableModule' }];
    const FORM_MODULE = [...NG_FORM_MODULE, ...NG_REACTIVE_FORM_MODULE, ...BASIC_MODULE, ...INPUT_MODULE, ...PAGE_MODULE, ...DESIGN_DIALOG_MODULE, { from: '@wm/components/data/form', name: 'FormModule' }];
    const WIDGET_IMPORTS = new Map([
        ['wm-accordion', ACCORDION_MODULE],
        ['wm-accordionpane', ACCORDION_MODULE],
        ['wm-anchor', BASIC_MODULE],
        ['wm-alertdialog', ALERT_DIALOG_MODULE],
        ['wm-audio', BASIC_MODULE],
        ['wm-barcodescanner', BARCODE_SCANNER_MODULE],
        ['wm-button', INPUT_MODULE],
        ['wm-buttongroup', INPUT_MODULE],
        ['wm-breadcrumb', BREAD_CRUMB_MODULE],
        ['wm-camera', CAMERA_MODULE],
        ['wm-calendar', CALENDAR_MODULE],
        ['wm-card', CARD_MODULE],
        ['wm-card-actions', CARD_MODULE],
        ['wm-card-content', CARD_MODULE],
        ['wm-card-footer', CARD_MODULE],
        ['wm-carousel', CAROUSEL_MODULE],
        ['wm-carousel-content', CAROUSEL_MODULE],
        ['wm-carousel-template', CAROUSEL_MODULE],
        ['wm-chart', CHART_MODULE],
        ['wm-checkbox', INPUT_MODULE],
        ['wm-checkboxset', INPUT_MODULE],
        ['wm-chips', CHIPS_MODULE],
        ['wm-colorpicker', COLOR_PICKER_MODULE],
        ['wm-confirmdialog', CONFIRM_DIALOG_MODULE],
        ['wm-content', CONTENT_MODULE],
        ['wm-currency', CURRENCY_MODULE],
        ['wm-date', EPOCH_MODULE],
        ['wm-datetime', EPOCH_MODULE],
        ['wm-dialog', DESIGN_DIALOG_MODULE],
        ['wm-footer', FOOTER_MODULE],
        ['wm-form', FORM_MODULE],
        ['wm-form-action', FORM_MODULE],
        ['wm-form-field', FORM_MODULE],
        ['wm-filter-field', FORM_MODULE],
        ['wm-fileupload', FILE_UPLOAD_MODULE],
        ['wm-gridrow', LAYOUT_GRID_MODULE],
        ['wm-gridcolumn', LAYOUT_GRID_MODULE],
        ['wm-header', HEADER_MODULE],
        ['wm-html', BASIC_MODULE],
        ['wm-icon', BASIC_MODULE],
        ['wm-iframe', BASIC_MODULE],
        ['wm-iframedialog', IFRAME_DIALOG_MODULE],
        ['wm-label', BASIC_MODULE],
        ['wm-layoutgrid', LAYOUT_GRID_MODULE],
        ['wm-left-panel', LEFT_PANEL_MODULE],
        ['wm-linearlayout', LINEAR_LAYOUT_MODULE],
        ['wm-linearlayoutitem', LINEAR_LAYOUT_MODULE],
        ['wm-list', LIST_MODULE],
        ['wm-livetable', LIVE_TABLE_MODULE],
        ['wm-login', LOGIN_MODULE],
        ['wm-logindialog', LOGIN_DIALOG_MODULE],
        ['wm-marquee', MARQUEE_MODULE],
        ['wm-menu', MENU_MODULE],
        ['wm-media-list', MEDIA_LIST_MODULE],
        ['wm-mobile-navbar', MOBILE_NAV_BAR_MODULE],
        ['wm-mobile-tabbar', MOBILE_TAB_BAR_MODULE],
        ['wm-nav', MENU_MODULE],
        ['wm-navbar', NAVBAR_MODULE],
        ['wm-nav-item', MENU_MODULE],
        ['wm-network-info-toaster', BASIC_MODULE],
        ['wm-number', INPUT_MODULE],
        ['wm-page', PAGE_MODULE],
        ['wm-layout', PAGE_MODULE],
        ['wm-page-content', PAGE_MODULE],
        ['wm-pagedialog', PARTIAL_DIALOG_MODULE],
        ['wm-pagination', PAGINATION_MODULE],
        ['wm-panel', PANEL_MODULE],
        ['wm-panel-footer', PANEL_MODULE],
        ['wm-picture', BASIC_MODULE],
        ['wm-popover', POPOVER_MODULE],
        ['wm-progress-bar', PROGRESS_MODULE],
        ['wm-prefab', PREFAB_MODULE],
        ['wm-prefab-container', PREFAB_MODULE],
        ['wm-progress-circle', PROGRESS_MODULE],
        ['wm-radioset', INPUT_MODULE],
        ['wm-rating', RATING_MODULE],
        ['wm-richtexteditor', RICH_TEXT_EDITOR_MODULE],
        ['wm-right-panel', RIGHT_PANEL_MODULE],
        ['wm-select', INPUT_MODULE],
        ['wm-search', SEARCH_MODULE],
        ['wm-segmented-content', SEGMENTED_CONTROL_MODULE],
        ['wm-segmented-control', SEGMENTED_CONTROL_MODULE],
        ['wm-slider', SLIDER_MODULE],
        ['wm-spinner', BASIC_MODULE],
        ['wm-switch', INPUT_MODULE],
        ['wm-table', TABLE_MODULE],
        ['wm-tabs', TABS_MODULE],
        ['wm-tabpane', TABS_MODULE],
        ['wm-text', INPUT_MODULE],
        ['wm-textarea', INPUT_MODULE],
        ['wm-time', EPOCH_MODULE],
        ['wm-tile', TILE_MODULE],
        ['wm-top-nav', TOP_NAV_MODULE],
        ['wm-tree', TREE_MODULE],
        ['wm-video', BASIC_MODULE],
        ['wm-wizard', WIZARD_MODULE],
        ['wm-wizardstep', WIZARD_MODULE],
    ]);

    const CSS_REGEX = {
        COMMENTS_FORMAT: /\/\*((?!\*\/).|\n)+\*\//g,
        SELECTOR_FORMAT: /[^\{\}]*\{/gi,
        SELECTOR_EXCLUDE_FORMAT: /(@keyframes|@media|@font-face|@comment[0-9]+|from|to|[0-9]+%)\b/i
    };
    const isString = v => typeof v === 'string';
    const OVERRIDES = {
        'accessroles': '*accessroles',
        'ng-if': '*ngIf',
        'showindevice': '*wmShowInDevice',
        'ng-class': '[ngClass]',
        'data-ng-class': '[ngClass]',
        'data-ng-src': 'src',
        'ng-src': 'src',
        'data-ng-href': 'href',
        'ng-href': 'href',
        'ng-disabled': 'disabled',
        'data-ng-disabled': 'disabled',
        'ng-model': '[ngModelOptions]="{standalone: true}" [(ngModel)]'
    };
    const getBoundToExpr = (value) => {
        if (!value) {
            return null;
        }
        value = value.trim();
        if (value.startsWith('bind:')) {
            return value.substr(5);
        }
    };
    const quoteAttr = v => {
        return ('' + v) /* Forces the conversion to string. */
            .replace(/&/g, '&amp;') /* This MUST be the 1st replacement. */
            .replace(/'/g, '&apos;') /* The 4 other predefined entities, required. */
            .replace(/"/g, '&quot;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');
    };
    const registry = new Map();
    const htmlParser = new compiler.HtmlParser();
    const empty = () => '';
    const isEvent = name => name[0] === 'o' && name[1] === 'n' && name[2] === '-';
    const getEventName = key => key.substr(3);
    const processBinding = (attr, expr) => [`${attr.name}.bind`, quoteAttr(expr)];
    const processEvent = attr => {
        const evtName = getEventName(attr.name);
        return [`${evtName}.event`, attr.value];
    };
    /**
     * Wraps the string with single quotes.
     * @param val
     */
    const wrapWithApos = (val) => {
        return `&apos;${val.replace(/&apos/g, '&quot').replace(/&quot/g, '\\&quot')}&apos;`;
    };
    const ELE_PREFIX = '.wm-app';
    const processAttr = attr => {
        let overridden = OVERRIDES[attr.name];
        const value = attr.valueSpan ? attr.value : undefined;
        // do not append showInDevice attribute for mobile application.
        if (attr.name === 'showindevice' && core.isMobileApp()) {
            overridden = '';
        }
        if (overridden) {
            /**
             * wrap value for accessroles with ''.
             * since accessroles is a structural directive, it will be transpiled to [accessroles]
             * hence, the value against it should be a computed string
             */
            if (attr.name === 'accessroles' || attr.name === 'showindevice') {
                return [overridden, `'${value}'`];
            }
            return [overridden, quoteAttr(value)];
        }
        if (isEvent(attr.name)) {
            return processEvent(attr);
        }
        const boundExpr = getBoundToExpr(attr.value);
        if (boundExpr) {
            return processBinding(attr, boundExpr);
        }
        return [attr.name, quoteAttr(value)];
    };
    const getDataSource = (dataSetExpr) => {
        const parts = dataSetExpr.split('.');
        if (parts[0] === 'Variables' || parts[0] === 'Widgets') {
            return `${parts[0]}.${parts[1]}`;
        }
    };
    const widgetChildAttrs = (() => {
        const childAttrs = new Map();
        const validChildAttrs = [
            `required`
        ];
        return {
            set: attrs => {
                attrs.forEach((val, key) => {
                    validChildAttrs.includes(key) && (childAttrs.set(key, val));
                });
            },
            get: attrs => {
                const fltrAttrs = new Map();
                childAttrs.forEach((val, key) => {
                    !attrs.get(key) && fltrAttrs.set(key, val);
                });
                return fltrAttrs;
            },
            clear: () => {
                childAttrs.clear();
            }
        };
    })();
    const setChildAttrs = attrs => {
        widgetChildAttrs.set(attrs);
        return '';
    };
    const getChildAttrs = attrs => {
        return getAttrMarkup(widgetChildAttrs.get(attrs));
    };
    const clearChildAttrs = () => {
        widgetChildAttrs.clear();
        return '';
    };
    const getFormMarkupAttr = attrs => {
        if (attrs.get('datavalue.bind')) {
            const onDataValueBinding = getDataSource(attrs.get('datavalue.bind'));
            attrs.set('datavaluesource.bind', onDataValueBinding);
        }
        return getAttrMarkup(attrs);
    };
    const getAttrMap = attrs => {
        const attrMap = new Map();
        attrs.forEach(attr => {
            let [attrName, attrValue] = processAttr(attr);
            attrMap.set(attrName, attrValue);
        });
        if (attrMap.get('dataset.bind')) {
            const dataSource = getDataSource(attrMap.get('dataset.bind'));
            if (dataSource) {
                attrMap.set('datasource.bind', dataSource);
            }
        }
        return attrMap;
    };
    const getAttrMarkup = (attrs) => {
        let attrMarkup = '';
        attrs.forEach((v, k) => {
            attrMarkup += ` ${k}`;
            if (v) {
                v = v.trim();
                if (k === '[ngClass]' && v.startsWith('{')) {
                    v = v.replace(/"/g, `'`);
                }
                if (k === 'show.bind' && attrs.get('deferload') === 'true') {
                    v = v + `" *lazyLoad="${wrapWithApos(v)}`;
                }
                attrMarkup += `="${v}"`;
                if (k === 'showindevice' && v !== 'all') {
                    const condition = [];
                    if (v.includes('xs')) {
                        condition.push('Viewport.isMobileType');
                    }
                    if (v.includes('sm')) {
                        condition.push('(Viewport.isTabletType && Viewport.orientation.isPortrait)');
                    }
                    if (v.includes('md')) {
                        condition.push('(Viewport.isTabletType && Viewport.orientation.isLandscape)');
                    }
                    attrMarkup += ` *ngIf="${condition.join(' || ')}"`;
                }
            }
        });
        return attrMarkup;
    };
    const getRequiredProviders = (nodeDef, providers, nodeAttrs) => {
        if (!nodeDef.requires) {
            return [];
        }
        let requires = nodeDef.requires;
        if (isString(requires)) {
            requires = [requires];
        }
        if (!Array.isArray(requires)) {
            return [];
        }
        return requires.map(require => {
            // for dynamic table assigning parent provide map to the child,
            for (let i = nodeAttrs.length - 1; i >= 0; i--) {
                if (nodeAttrs[i].name === 'tableName') {
                    return nodeDef[nodeAttrs[i].value];
                }
            }
            for (let i = providers.length - 1; i >= 0; i--) {
                if (providers[i].nodeName === require) {
                    return providers[i].provide;
                }
            }
        });
    };
    const DIMENSION_PROPS = ['padding', 'borderwidth', 'margin'];
    const SEPARATOR = ' ', UNSET = 'unset';
    const setDimensionProp = (cssObj, key, nv) => {
        let cssKey = key, val, top, right, bottom, left, suffix = '';
        function setVal(prop, value) {
            // if the value is UNSET, reset the existing value
            if (value === UNSET) {
                value = '';
            }
            cssObj[cssKey + prop + suffix] = value;
        }
        if (key === 'borderwidth') {
            suffix = 'width';
            cssKey = 'border';
        }
        val = nv;
        if (val.indexOf(UNSET) !== -1) {
            val = val.split(SEPARATOR);
            top = val[0];
            right = val[1] || val[0];
            bottom = val[2] || val[0];
            left = val[3] || val[1] || val[0];
            setVal('top', top);
            setVal('right', right);
            setVal('bottom', bottom);
            setVal('left', left);
        }
        else {
            if (key === 'borderwidth') {
                cssKey = 'borderwidth';
            }
            cssObj[cssKey] = nv;
        }
    };
    const processDimensionAttributes = attrMap => {
        const attrKeys = Array.from(attrMap.keys());
        attrKeys.forEach((attrKey) => {
            if (DIMENSION_PROPS.includes(attrKey)) {
                const cssObj = {}, attrValue = attrMap.get(attrKey);
                attrMap.delete(attrKey);
                setDimensionProp(cssObj, attrKey, attrValue);
                Object.keys(cssObj).forEach(key => {
                    if (cssObj[key]) {
                        attrMap.set(key, cssObj[key]);
                    }
                });
            }
        });
    };
    // replace <:svg:svg> -> <svg>, <:svg:*> -> <svg:*>
    const getNodeName = name => name.replace(':svg:svg', 'svg').replace(':svg:', 'svg:');
    const processNode = (node, importCollector, providers) => {
        const nodeDef = registry.get(node.name);
        let pre, post, template;
        if (nodeDef) {
            pre = nodeDef.pre || empty;
            post = nodeDef.post || empty;
            template = nodeDef.template || empty;
        }
        let markup = '';
        let attrMap;
        let requiredProviders;
        let shared;
        if (!providers) {
            providers = [];
        }
        const isElementType = node instanceof compiler.Element;
        if (isElementType) {
            let provideInfo;
            if (nodeDef) {
                requiredProviders = getRequiredProviders(nodeDef, providers, node.attrs);
                shared = new Map();
                template(node, shared, ...requiredProviders);
            }
            attrMap = getAttrMap(node.attrs);
            processDimensionAttributes(attrMap);
            const nodeName = getNodeName(node.name);
            if (nodeDef) {
                markup = pre(attrMap, shared, ...requiredProviders);
                if (nodeDef.provide) {
                    provideInfo = {
                        nodeName: node.name,
                        provide: lodashEs.isFunction(nodeDef.provide) ? nodeDef.provide(attrMap, shared, ...requiredProviders) : nodeDef.provide
                    };
                    // For table node, assigning parent provide map to the child, as child requires some parent provide attrs.
                    if (node.name === 'wm-table') {
                        const tableColNodeDefn = registry.get('wm-table-column');
                        tableColNodeDefn[lodashEs.find(node.attrs, (el) => el.name === 'name').value + provideInfo.provide.get('table_reference')] = provideInfo.provide;
                        registry.set('wm-table-column', tableColNodeDefn);
                    }
                    providers.push(provideInfo);
                }
            }
            else {
                markup = `<${nodeName} ${getAttrMarkup(attrMap)}>`;
            }
            node.children.forEach((child) => {
                if (child.attrs) {
                    let showInDeviceAttr, accessRolesAttr, deferLoadAttr, showAttr;
                    child.attrs.forEach(function (attr) {
                        if (attr.name === 'showindevice') {
                            showInDeviceAttr = attr;
                        }
                        else if (attr.name === 'accessroles') {
                            accessRolesAttr = attr;
                        }
                        else if (attr.name === 'deferload') {
                            deferLoadAttr = attr;
                        }
                        else if (attr.name === 'show') {
                            showAttr = attr;
                        }
                    });
                    if ((showInDeviceAttr && accessRolesAttr) || (showInDeviceAttr && deferLoadAttr) || (accessRolesAttr && deferLoadAttr)) {
                        /* If more than one out of showindevice, accessroles and deferload exist for a widget, add ng-container wrappers to fix angular limitation
                           of applying only one structural directive to an element.
                        *  */
                        const noSpan = {};
                        const showInDeviceContainer = showInDeviceAttr ? new compiler.Element('ng-container', [], [], noSpan, noSpan, noSpan) : '';
                        const accessRolesContainer = accessRolesAttr ? new compiler.Element('ng-container', [], [], noSpan, noSpan, noSpan) : '';
                        const deferLoadContainer = deferLoadAttr ? new compiler.Element('ng-container', [], [], noSpan, noSpan, noSpan) : '';
                        if (showInDeviceContainer) {
                            showInDeviceContainer.attrs.push(showInDeviceAttr);
                        }
                        if (accessRolesContainer) {
                            accessRolesContainer.attrs.push(accessRolesAttr);
                        }
                        if (deferLoadContainer) {
                            deferLoadContainer.attrs.push(deferLoadAttr);
                            if (showAttr) {
                                deferLoadContainer.attrs.push(showAttr);
                            }
                        }
                        lodashEs.remove(child.attrs, function (attr) {
                            // @ts-ignore
                            return attr.name === 'showindevice' || attr.name === 'accessroles' || attr.name === 'deferload';
                        });
                        let childContainer, parentContainer;
                        if (showInDeviceAttr && accessRolesAttr) {
                            childContainer = showInDeviceContainer;
                            parentContainer = accessRolesContainer;
                        }
                        else if (showInDeviceAttr && deferLoadAttr) {
                            childContainer = showInDeviceContainer;
                            parentContainer = deferLoadContainer;
                        }
                        else if (accessRolesAttr && deferLoadAttr) {
                            childContainer = deferLoadContainer;
                            parentContainer = accessRolesContainer;
                        }
                        // wrap current node elements inside first ng-container(childContainer) and that container's elements inside another ng-container(parentContainer)
                        childContainer.children = [child];
                        parentContainer.children = [childContainer];
                        // if all three directives exist, create another wrapper for third ng-container(grandParentContainer)
                        if (showInDeviceAttr && accessRolesAttr && deferLoadAttr) {
                            const grandParentContainer = deferLoadContainer;
                            grandParentContainer.children = [parentContainer];
                            child = grandParentContainer;
                        }
                        else {
                            child = parentContainer;
                        }
                    }
                }
                return markup += processNode(child, importCollector, providers);
            });
            if (nodeDef) {
                if (provideInfo) {
                    providers.splice(providers.indexOf(provideInfo), 1);
                }
                markup += post(attrMap, shared, ...requiredProviders);
            }
            else {
                if (node.endSourceSpan && !compiler.getHtmlTagDefinition(node.name).isVoid) {
                    markup += `</${nodeName}>`;
                }
            }
        }
        else if (node instanceof compiler.Text) {
            markup += node.value;
        }
        else ;
        importCollector(WIDGET_IMPORTS.get(node.name));
        if (nodeDef && nodeDef.imports) {
            let imports = [];
            if (typeof nodeDef.imports === 'function') {
                imports = nodeDef.imports(attrMap);
            }
            else {
                imports = nodeDef.imports;
            }
            imports.forEach(i => {
                importCollector(WIDGET_IMPORTS.get(i));
            });
        }
        return markup;
    };
    const transpile = (markup = '') => {
        if (!markup.length) {
            return;
        }
        let requiredWMComponents = [];
        const nodes = htmlParser.parse(markup, '');
        if (nodes.errors.length) {
            return;
        }
        let output = '';
        for (const node of nodes.rootNodes) {
            output += processNode(node, (imports) => {
                if (imports) {
                    requiredWMComponents = requiredWMComponents.concat(imports);
                }
            });
        }
        requiredWMComponents = lodashEs.uniqWith(requiredWMComponents, lodashEs.isEqual);
        requiredWMComponents = lodashEs.sortBy(requiredWMComponents, ['from', 'name']);
        return {
            markup: output,
            requiredWMComponents: requiredWMComponents
        };
    };
    const register = (nodeName, nodeDefFn) => registry.set(nodeName, nodeDefFn());
    const scopeComponentStyles = (componentName, componentType, styles = '') => {
        componentName = componentName.toLowerCase();
        const comments = {};
        let commentCount = 0;
        if (styles.startsWith('/*DISABLE_SCOPING*/')) {
            return styles;
        }
        styles = styles.replace(CSS_REGEX.COMMENTS_FORMAT, comment => {
            const key = `@comment${commentCount++}{`;
            comments[key] = comment;
            return key;
        });
        styles = styles.replace(CSS_REGEX.SELECTOR_FORMAT, (selector) => {
            if (!CSS_REGEX.SELECTOR_EXCLUDE_FORMAT.test(selector)) {
                const firstNonSpaceCharIndex = selector.match(/\S/).index;
                let prefixSpaceCharSeq = '';
                if (firstNonSpaceCharIndex > 0) {
                    prefixSpaceCharSeq = selector.substring(0, firstNonSpaceCharIndex);
                    selector = selector.substring(firstNonSpaceCharIndex);
                }
                if (!selector.startsWith('/*') && selector.trim().length > 0) {
                    // splits the selector by commas and we iterate over the array and add page level scoping and join it.
                    selector = selector.split(',').map(s => {
                        let prefix = ELE_PREFIX;
                        s = s.trim();
                        const spaceIndex = s.indexOf(' ');
                        if (s.startsWith(ELE_PREFIX)) {
                            if (spaceIndex > 0) {
                                prefix = s.substring(0, spaceIndex);
                                s = s.substring(spaceIndex + 1);
                            }
                            else {
                                return s;
                            }
                        }
                        if (componentType === 0 || componentType === 'PAGE') {
                            s = `${prefix} app-page-${componentName} ${s}`;
                        }
                        else if (componentType === 1 || componentType === 'PREFAB') {
                            s = `${prefix} app-prefab-${componentName} ${s}`;
                        }
                        else if (componentType === 2 || componentType === 'PARTIAL') {
                            s = `${prefix} app-partial-${componentName} ${s}`;
                        }
                        return s;
                    }).join(',');
                }
                selector = prefixSpaceCharSeq + selector;
            }
            return selector;
        });
        for (const key in comments) {
            styles = styles.replace(key, comments[key]);
        }
        return styles;
    };

    exports.WIDGET_IMPORTS = WIDGET_IMPORTS;
    exports.clearChildAttrs = clearChildAttrs;
    exports.getAttrMarkup = getAttrMarkup;
    exports.getBoundToExpr = getBoundToExpr;
    exports.getChildAttrs = getChildAttrs;
    exports.getDataSource = getDataSource;
    exports.getFormMarkupAttr = getFormMarkupAttr;
    exports.processNode = processNode;
    exports.register = register;
    exports.scopeComponentStyles = scopeComponentStyles;
    exports.setChildAttrs = setChildAttrs;
    exports.transpile = transpile;

}));
