/// <summary>
        /// Extract the razor code fragment from a line of Javascript.
        /// Input: A line of Javascript containing an @. The @ prefixes the razor code.
        /// Note. the line may contain several fragments of razor.
        /// The razor code is prefixed with @, it will probably be surrounded by quotes (single or double), but not always!
        /// </summary>
        public List<Fragment> Evaluate(string jsLine)
        {
            // we can't handle lines containing "@Url
            if (jsLine.Contains("\"@Url")
            || jsLine.Contains("@{") )
            {
                throw new UnhandledPatternException(jsLine);
            }

            List<Fragment> output = new List<Fragment>();

            // Multi fragment line?
            if (jsLine.ToCharArray().Count(c => c == '@') > 1)
            {
                return ProcessMultiFragmentLine(jsLine);
            }

            Fragment fragment = new Fragment();

            int atPosition = jsLine.IndexOf("@");

            char firstCharacterToLeft = jsLine.Substring(atPosition - 1, 1).ToCharArray()[0];   // take character to the left

            // Immediately Quoted?
            // example: '@decommisionReason'
            if (Constants.CharacterConstants.Quotes.Contains(firstCharacterToLeft)) // is a quote?
            {
                int rightDelimeterPos = GetRightDelimiterPosition(jsLine, atPosition, firstCharacterToLeft);

                if (rightDelimeterPos > 0)
                {
                    fragment.Text = jsLine.Substring(atPosition - 1, rightDelimeterPos - atPosition + 2); // include the quote delimiters
                    fragment.FragType = FragType.Quoted;
                    output.Add(fragment);
                    return output;
                }
                // We can't find the matching quote, or a space was hit before hitting the right quote
                throw new UnhandledPatternException(jsLine);
            }

            // Non quoted?
            // example: globalFunction = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.GlobalFunctionVmList));
            if (firstCharacterToLeft == ' ')
            {
                // if there's a quote, play safe and terminate
                if (jsLine.IndexOf("'", System.StringComparison.Ordinal) > 0)
                {
                    throw new UnhandledPatternException(jsLine);
                }

                // Assume its unquoted, but terminated by a ;
                int endDelimierPosition = jsLine.LastIndexOf(";");
                if (endDelimierPosition == -1) // is there a ; ?
                {
                    throw new UnhandledPatternException(jsLine);
                }

                fragment.Text = jsLine.Substring(atPosition, endDelimierPosition - atPosition); // don't include delimiters
                fragment.FragType = FragType.Unquoted;
                output.Add(fragment);
                return output;
            }

            // Its not a pattern we are confident we recognize, it will have to be done manually
            throw new UncaughtPatternException();
        }
        private List<Fragment> ProcessMultiFragmentLine(string jsline)
        {
            // I'm assuming the follow pattern of input
            // data: "{'docId1':'" + '@ViewBag.docid' + "','conditionType1':'" + '@ViewBag.doctype' + "'}"

            List<Fragment> result = new List<Fragment>();

            int pos = 0;
            foreach (char c in jsline) // scan the line char by char
            {
                if (c == '@')
                {
                    string previousChar = jsline.Substring(pos - 1, 1);

                    if (previousChar == "'" || previousChar == "\"") // prefixed by quote ?
                    {
                        int endQuotePosition = GetEndQuotePosition(jsline, pos, previousChar);

                        Fragment fragment = new Fragment();
                        fragment.Text = jsline.Substring(pos - 1, endQuotePosition - pos + 2);
                        fragment.FragType = FragType.Quoted;
                        result.Add(fragment);
                    }
                    else
                    {
                        throw new UnhandledPatternException(jsline);
                    }
                }
                pos++;
            }

            return result;
        }