/// <summary> /// Looks for tab stops in the specified content and returns a processed version with expanded /// placeholders and tab stops found. /// </summary> /// <param name="engine">V8 instance with Emmet engine compiled in it.</param> /// <param name="content">Expanded abbreviation content.</param> /// <exception cref="Exception{EmmetEngineExceptionArgs}"> /// Indicates that Emmet engine has failed to parse the specified content. /// </exception> public static TabStopsParser ParseContent(V8Engine engine, string content) { ObjectHandle tabStopsUtil = engine.DynamicGlobalObject.window.emmet.tabStops; Handle extractResult = tabStopsUtil.Call("extract", null, engine.CreateValue(content)); if (extractResult.IsError) { var ex = new EmmetEngineExceptionArgs( "Error while trying to extract tab stops.", extractResult); throw new Exception <EmmetEngineExceptionArgs>(ex); } TabStopsParser retVal = new TabStopsParser(); ObjectHandle tabStopsObj = (ObjectHandle)extractResult; retVal.Content = tabStopsObj.GetProperty(@"text").AsString; ObjectHandle tabStopsList = tabStopsObj.GetProperty(@"tabstops"); // Tab stops should be added before modifying document so that editor can track their position. int tabStopsCount = tabStopsList.ArrayLength; if (tabStopsCount > 0) { retVal.TabStops = new Range[tabStopsCount]; retVal.TabStopGroups = new int[tabStopsCount]; for (int i = 0; i < tabStopsCount; i++) { ObjectHandle tabStopObj = tabStopsList.GetProperty(i.ToString()); int start = tabStopObj.GetProperty("start").AsInt32; int end = tabStopObj.GetProperty("end").AsInt32; int group = tabStopObj.GetProperty("group").AsInt32; retVal.TabStops[i] = new Range(start, end); retVal.TabStopGroups[i] = group; } } return(retVal); }
/// <summary> /// Looks for tab stops in the specified content and returns a processed version with expanded /// placeholders and tab stops found. /// </summary> /// <param name="content">Expanded abbreviation content.</param> /// <param name="offset">(Optional) The offset of the content in containing document.</param> public static TabStopsParser ParseContent(string content, int offset = 0) { var tabStops = new List <Span>(5); int tabStopOffset = 0; var retVal = new TabStopsParser(); retVal.Content = Parser.Replace( content, (Match m) => { string replacement = m.Groups[1]?.Value ?? string.Empty; tabStops.Add(new Span(offset + m.Index - tabStopOffset, replacement.Length)); tabStopOffset += m.Length - replacement.Length; return(replacement); }); retVal.TabStops = tabStops.ToArray(); return(retVal); }
/// <summary> /// Looks for tab stops in the specified content and returns a processed version with expanded /// placeholders and tab stops found. /// </summary> /// <param name="engine">V8 instance with Emmet engine compiled in it.</param> /// <param name="content">Expanded abbreviation content.</param> /// <exception cref="Exception{EmmetEngineExceptionArgs}"> /// Indicates that Emmet engine has failed to parse the specified content. /// </exception> public static TabStopsParser ParseContent(V8Engine engine, string content) { ObjectHandle tabStopsUtil = engine.DynamicGlobalObject.window.emmet.tabStops; Handle extractResult = tabStopsUtil.Call("extract", null, engine.CreateValue(content)); if (extractResult.IsError) { var ex = new EmmetEngineExceptionArgs( "Error while trying to extract tab stops.", extractResult); throw new Exception<EmmetEngineExceptionArgs>(ex); } TabStopsParser retVal = new TabStopsParser(); ObjectHandle tabStopsObj = (ObjectHandle)extractResult; retVal.Content = tabStopsObj.GetProperty(@"text").AsString; ObjectHandle tabStopsList = tabStopsObj.GetProperty(@"tabstops"); // Tab stops should be added before modifying document so that editor can track their position. int tabStopsCount = tabStopsList.ArrayLength; if (tabStopsCount > 0) { retVal.TabStops = new Range[tabStopsCount]; retVal.TabStopGroups = new int[tabStopsCount]; for (int i = 0; i < tabStopsCount; i++) { ObjectHandle tabStopObj = tabStopsList.GetProperty(i.ToString()); int start = tabStopObj.GetProperty("start").AsInt32; int end = tabStopObj.GetProperty("end").AsInt32; int group = tabStopObj.GetProperty("group").AsInt32; retVal.TabStops[i] = new Range(start, end); retVal.TabStopGroups[i] = group; } } return retVal; }
/// <summary> /// JavaScript callback. Replace editor's content or it's part (from <code>start</code> to /// <code>end</code> index). If <code>value</code> contains <code>caret_placeholder</code>, the editor /// will put caret into this position. If you skip <code>start</code> and <code>end</code> arguments, /// the whole target's content will be replaced with <code>value</code>. /// If you pass <code>start</code> argument only, the <code>value</code> will be placed at /// <code>start</code> string index of current content. /// If you pass <code>start</code> and <code>end</code> arguments, the corresponding substring of /// current target's content will be replaced with <code>value</code>. /// </summary> public InternalHandle ReplaceContent( V8Engine engine, bool isConstructCall, InternalHandle self, params InternalHandle[] args) { string rawContent = args[0].AsString; int regionStart = args.Length > 1 ? args[1].AsInt32 : -1; int regionLength = args.Length > 2 ? args[2].AsInt32 - regionStart : 0; bool indentContent = args.Length == 4 ? args[3].AsBoolean : true; this.Trace($"Received new content for the editor: {rawContent}"); // Extract tab stops placeholders from the specified content. var tabStops = TabStopsParser.ParseContent(engine, rawContent); _editor.ReplaceContentRange(tabStops.Content, regionStart, regionStart + regionLength); if (null != tabStops.TabStops) { Range[] tabStopRanges = tabStops.TabStops; // Tab stop offsets are relative to the newly generated content ranges, we need to convert // them to the document-wide offsets. if (regionStart > 0) { tabStopRanges = tabStopRanges.Select( item => new Range(item.Start + regionStart, item.End + regionStart)).ToArray(); } _editor.TrackTabStops(tabStopRanges, tabStops.TabStopGroups); } if (indentContent) { _editor.FormatRegion(regionStart, regionStart + tabStops.Content.Length); } return(engine.CreateValue(true)); }