/// <summary>
        /// Register a shortcode that is defined in the data store.
        /// The definition of a dynamic shortcode can be changed at runtime.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="shortcodeFactoryMethod"></param>
        public void RegisterShortcode(DynamicShortcodeDefinition shortcodeDefinition)
        {
            if (shortcodeDefinition == null)
            {
                throw new Exception("Shortcode definition is required.");
            }

            if (shortcodeDefinition.ElementType == LavaShortcodeTypeSpecifier.Inline)
            {
                // Create a new factory method that returns an initialized Shortcode Tag element.
                Func <string, ILavaTag> tagFactoryMethod = (tagName) =>
                {
                    // Call the factory method we have been passed to retrieve the definition of the shortcode.
                    // The definition may change at runtime, so we need to execute the factory method every time we create a new shortcode instance.
                    var shortCodeName = LavaUtilityHelper.GetShortcodeNameFromLiquidElementName(tagName);

                    var shortcodeInstance = new DynamicShortcodeTag();

                    shortcodeInstance.Initialize(shortcodeDefinition, this);

                    return(shortcodeInstance);
                };

                // Register the shortcode as a custom tag, but use a decorated registration name that will not collide with a regular element name.
                var registrationKey = LavaUtilityHelper.GetLiquidElementNameFromShortcodeName(shortcodeDefinition.Name);

                RegisterTag(registrationKey, tagFactoryMethod);
            }
            else
            {
                // Create a new factory method that returns an initialized Shortcode Block element.
                Func <string, ILavaBlock> blockFactoryMethod = (blockName) =>
                {
                    // Call the factory method we have been passed to retrieve the definition of the shortcode.
                    // The definition may change at runtime, so we need to execute the factory method for each new shortcode instance.
                    var shortCodeName = LavaUtilityHelper.GetShortcodeNameFromLiquidElementName(blockName);

                    var shortcodeInstance = new DynamicShortcodeBlock(shortcodeDefinition, this);

                    return(shortcodeInstance);
                };

                // Register the shortcode as a custom block, but use a decorated registration name that will not collide with a regular element name.
                var registrationKey = LavaUtilityHelper.GetLiquidElementNameFromShortcodeName(shortcodeDefinition.Name);

                RegisterBlock(registrationKey, blockFactoryMethod);
            }
        }
        /// <summary>
        /// Register a shortcode that is defined in the data store.
        /// The definition of a dynamic shortcode can be changed at runtime.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="shortcodeFactoryMethod"></param>
        public void RegisterShortcode(string name, Func <string, DynamicShortcodeDefinition> shortcodeFactoryMethod)
        {
            // Create a default instance so we can retrieve the properties of the shortcode.
            var instance = shortcodeFactoryMethod(name);

            if (instance == null)
            {
                throw new Exception($"Shortcode factory could not provide a valid instance for \"{name}\" .");
            }

            if (instance.ElementType == LavaShortcodeTypeSpecifier.Inline)
            {
                // Create a new factory method that returns an initialized Shortcode Tag element.
                Func <string, ILavaTag> tagFactoryMethod = (tagName) =>
                {
                    var shortcodeInstance = GetShortcodeFromFactory <DynamicShortcodeTag>(tagName, shortcodeFactoryMethod);

                    return(shortcodeInstance);
                };

                // Register the shortcode as a custom tag, but use a decorated registration name that will not collide with a regular element name.
                var registrationKey = LavaUtilityHelper.GetLiquidElementNameFromShortcodeName(name);

                RegisterTag(registrationKey, tagFactoryMethod);
            }
            else
            {
                // Create a new factory method that returns an initialized Shortcode Block element.
                Func <string, ILavaBlock> blockFactoryMethod = (blockName) =>
                {
                    // Call the factory method we have been passed to retrieve the definition of the shortcode.
                    // The definition may change at runtime, so we need to execute the factory method for each new shortcode instance.
                    var shortCodeName = LavaUtilityHelper.GetShortcodeNameFromLiquidElementName(blockName);

                    var shortcodeDefinition = shortcodeFactoryMethod(shortCodeName);

                    var shortcodeInstance = new DynamicShortcodeBlock(shortcodeDefinition, this);

                    return(shortcodeInstance);
                };

                // Register the shortcode as a custom block, but use a decorated registration name that will not collide with a regular element name.
                var registrationKey = LavaUtilityHelper.GetLiquidElementNameFromShortcodeName(name);

                RegisterBlock(registrationKey, blockFactoryMethod);
            }
        }