private static string GetCode(ScriptLoader.Chunk chunk, DialogueActionStage stage)
        {
            var          sb        = new StringBuilder();
            var          stageName = GetStageName(stage);
            const string stageKey  = "stage";

            foreach (var block in chunk.blocks)
            {
                if (block.type == BlockType.LazyExecution)
                {
                    if (!block.attributes.TryGetValue(stageKey, out var stageValue))
                    {
                        stageValue = "";
                    }

                    if (!stageValue.Equals(stageName))
                    {
                        continue;
                    }

                    sb.Append(block.content);
                    sb.Append("\n");
                }
            }

            var code = sb.ToString().Trim();

            if (code == "")
            {
                code = null;
            }

            // if (code != null) Debug.Log($"code: <color=blue>{code}</color>");
            return(code);
        }
        /// <remarks>
        /// There can be multiple dialogue texts in the same chunk. They are concatenated into one, separated with newlines.
        /// </remarks>
        private static string GetText(ScriptLoader.Chunk chunk)
        {
            var sb    = new StringBuilder();
            var first = true;

            foreach (var block in chunk.blocks)
            {
                if (block.type == BlockType.Text)
                {
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        sb.Append('\n');
                    }

                    sb.Append(block.content);
                }
            }

            // Normalize line endings
            sb.Replace("\r", "");

            var text = sb.ToString();

            // Markdown syntaxes used in tutorials
            // They are not in the NovaScript spec. If they interfere with your scenarios or you have performance concern,
            // you can comment out them.
            text = Regex.Replace(text, @"`([^`]*)`", @"<style=Code>$1</style>");
            text = Regex.Replace(text, @"\[([^\]]*)\]\(([^\)]*)\)", @"<link=""$2""><style=Link>$1</style></link>");

            // Debug.Log($"text: <color=green>{text}</color>");
            return(text);
        }