@podlite/editor-react 0.0.18 → 0.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.tsx CHANGED
@@ -1,73 +1,72 @@
1
- import * as React from 'react'
2
- import { Controlled as CodeMirrorControlled, UnControlled as CodeMirror} from 'react-codemirror2'
1
+ import React from 'react'
2
+ import { Controlled as CodeMirrorControlled, UnControlled as CodeMirror } from 'react-codemirror2'
3
3
  import CMirror from 'codemirror'
4
4
  import dictionary from './dict'
5
- import { useState, useEffect, useRef, useMemo } from 'react'
6
- import {isValidElementType, isElement} from 'react-is'
5
+ import { useState, useEffect, useRef } from 'react'
6
+ import { isElement } from 'react-is'
7
7
 
8
8
  // TODO: use bundler to add into package
9
9
  // import '../../../node_modules/codemirror/lib/codemirror.css';
10
- import 'codemirror/mode/gfm/gfm';
11
- import "codemirror/addon/hint/show-hint";
12
- import 'codemirror/addon/hint/show-hint.css';
13
- import './Editor.css';
10
+ import 'codemirror/mode/gfm/gfm'
11
+ import 'codemirror/addon/hint/show-hint'
12
+ import 'codemirror/addon/hint/show-hint.css'
13
+ import './Editor.css'
14
14
  import { addVMargin, getSuggestionContextForLine, templateGetSelectionPos } from './helpers'
15
15
 
16
-
17
16
  //@ts-ignore
18
17
  function useDebouncedEffect(fn, deps, time) {
19
- const dependencies = [...deps, time]
18
+ const dependencies = [...deps, time]
20
19
  useEffect(() => {
21
- const timeout = setTimeout(fn, time);
20
+ const timeout = setTimeout(fn, time)
22
21
  return () => {
23
- clearTimeout(timeout);
22
+ clearTimeout(timeout)
24
23
  }
25
- }, dependencies);
24
+ }, dependencies)
26
25
  }
27
26
 
28
- /* set window title */
27
+ /* set window title */
29
28
  // @ts-ignore
30
29
  // const setWindowTitle = (title: string) => { vmd.setWindowTitle(title) }
31
- export interface ConverterResult {
32
- errors?:any,
33
- result:any
30
+ export interface ConverterResult {
31
+ errors?: any
32
+ result: any
34
33
  }
35
34
 
36
35
  let instanceCM = null
37
- type Props={
38
- content: string,
39
- onChangeSource:Function,
40
- sourceType?: 'pod6' | 'md',
41
- onConvertSource: (source:string)=>ConverterResult,
42
- onSavePressed?: Function,
43
- isDarkTheme? : boolean,
44
- isLineNumbers?: boolean,
45
- isAutoComplete?: boolean,
46
- isPreviewModeEnabled? :boolean
47
- isControlled?:boolean
36
+ type Props = {
37
+ content: string
38
+ onChangeSource: Function
39
+ sourceType?: 'pod6' | 'md'
40
+ onConvertSource: (source: string) => ConverterResult
41
+ onSavePressed?: Function
42
+ isDarkTheme?: boolean
43
+ isLineNumbers?: boolean
44
+ isAutoComplete?: boolean
45
+ isPreviewModeEnabled?: boolean
46
+ isControlled?: boolean
48
47
  }
49
48
 
50
- export default ({
51
- onChangeSource = ()=>{},
52
- content,
53
- isDarkTheme = false,
54
- isLineNumbers = false,
55
- isPreviewModeEnabled = false,
56
- onConvertSource,
57
- onSavePressed = () => { },
58
- sourceType = 'pod6',
59
- isControlled=false,
60
- isAutoComplete = true,
61
- }: Props) => {
49
+ export const Editor = ({
50
+ onChangeSource = () => {},
51
+ content,
52
+ isDarkTheme = false,
53
+ isLineNumbers = false,
54
+ isPreviewModeEnabled = false,
55
+ onConvertSource,
56
+ onSavePressed = () => {},
57
+ sourceType = 'pod6',
58
+ isControlled = false,
59
+ isAutoComplete = true,
60
+ }: Props) => {
62
61
  const [text, updateText] = useState(content)
63
62
 
64
63
  const [marks, updateMarks] = useState([])
65
64
  const [, updateScrollMap] = useState([])
66
-
65
+
67
66
  const [isPreviewMode, setPreviewMode] = useState(isPreviewModeEnabled)
68
67
 
69
- const [isPreviewScroll, setPreviewScrolling] = useState(false);
70
- const refValue = useRef(isPreviewScroll);
68
+ const [isPreviewScroll, setPreviewScrolling] = useState(false)
69
+ const refValue = useRef(isPreviewScroll)
71
70
  const [showTree, setShowTree] = useState(false)
72
71
 
73
72
  const [filePath, setFilePath] = useState('')
@@ -77,275 +76,297 @@ export default ({
77
76
 
78
77
  const [fileLoading, setFileLoading] = useState(true)
79
78
 
80
- useEffect(()=>{
81
- updateText(content)
82
- },[content])
79
+ useEffect(() => {
80
+ updateText(content)
81
+ }, [content])
82
+
83
+ const [result, updateResult] = useState<ConverterResult>()
84
+ useDebouncedEffect(
85
+ () => {
86
+ updateResult(onConvertSource(text))
87
+ },
88
+ [text],
89
+ 50,
90
+ )
83
91
 
84
- const [result, updateResult] = useState<ConverterResult>()
85
- useDebouncedEffect(() => {
86
- updateResult(onConvertSource(text))
87
- }, [text], 50)
88
-
89
92
  const inputEl = useRef(null)
90
93
 
91
- // hot keys
92
- useEffect( () => {
93
- const saveFileAction = () => {
94
- if (isChanged) {
95
- console.warn("Save File")
94
+ // hot keys
95
+ useEffect(() => {
96
+ const saveFileAction = () => {
97
+ if (isChanged) {
98
+ console.warn('Save File')
96
99
  onSavePressed(text)
97
-
100
+ }
98
101
  }
99
- }
100
- })
101
-
102
-
103
- useEffect(() => {
104
- refValue.current = isPreviewScroll;
105
- });
106
- var options: CMirror.EditorConfiguration = {
107
- lineNumbers: isLineNumbers,
108
- inputStyle: "contenteditable",
109
- //@ts-ignore
110
- spellcheck: true,
111
- autofocus:true,
112
- lineWrapping:true,
113
- viewportMargin:Infinity,
114
- mode: sourceType !== 'md' ? null :
115
- {
116
- name: "gfm",
117
- tokenTypeOverrides: {
118
- emoji: "emoji"
119
- }
120
- },
121
- theme: isDarkTheme ? "duotone-dark" : "default"
122
- };
102
+ })
123
103
 
104
+ useEffect(() => {
105
+ refValue.current = isPreviewScroll
106
+ })
107
+ var options: CMirror.EditorConfiguration = {
108
+ lineNumbers: isLineNumbers,
109
+ inputStyle: 'contenteditable',
110
+ //@ts-ignore
111
+ spellcheck: true,
112
+ autofocus: true,
113
+ lineWrapping: true,
114
+ viewportMargin: Infinity,
115
+ mode:
116
+ sourceType !== 'md'
117
+ ? null
118
+ : {
119
+ name: 'gfm',
120
+ tokenTypeOverrides: {
121
+ emoji: 'emoji',
122
+ },
123
+ },
124
+ theme: isDarkTheme ? 'duotone-dark' : 'default',
125
+ }
124
126
 
125
- const previewEl = useRef(null)
127
+ const previewEl = useRef(null)
126
128
 
127
- useEffect(() => {
128
- //@ts-ignore
129
- const newScrollMap = [...document.querySelectorAll('.line-src')]
130
- .map(n => {
131
- const line = parseInt(n.getAttribute('data-line'),10 )
132
- //@ts-ignore
133
- const offsetTop = n.offsetTop
134
- return { line, offsetTop}
135
- })
136
- //@ts-ignore
137
- updateScrollMap(newScrollMap)
138
- //@ts-ignore
139
- const listener = (e) => {
140
- if (!isPreviewScroll ) {return}
141
- let element = e.target
129
+ useEffect(() => {
130
+ //@ts-ignore
131
+ const newScrollMap = [...document.querySelectorAll('.line-src')].map(n => {
132
+ const line = parseInt(n.getAttribute('data-line'), 10)
133
+ //@ts-ignore
134
+ const offsetTop = n.offsetTop
135
+ return { line, offsetTop }
136
+ })
137
+ //@ts-ignore
138
+ updateScrollMap(newScrollMap)
142
139
  //@ts-ignore
143
- const getLine = (offset) => {
144
- const c = newScrollMap.filter( i => i.offsetTop > offset )
145
- const lineElement = c.shift() || newScrollMap[ newScrollMap.length - 1 ]
146
- if (!lineElement) {
140
+ const listener = e => {
141
+ if (!isPreviewScroll) {
142
+ return
143
+ }
144
+ let element = e.target
145
+ //@ts-ignore
146
+ const getLine = offset => {
147
+ const c = newScrollMap.filter(i => i.offsetTop > offset)
148
+ const lineElement = c.shift() || newScrollMap[newScrollMap.length - 1]
149
+ if (!lineElement) {
147
150
  console.warn(`[podlite-editor] can't get line for offset. Forget add .line-src ?`)
151
+ }
152
+ return lineElement.line
148
153
  }
149
- return lineElement.line
154
+ const line = getLine(element.scrollTop)
155
+ if (instanceCM) {
156
+ const t = element.scrollTop === 0 ? 0 : instanceCM.charCoords({ line: line, ch: 0 }, 'local').top
157
+ instanceCM.scrollTo(null, t)
150
158
  }
151
- const line = getLine(element.scrollTop)
152
- if (instanceCM) {
153
- const t = element.scrollTop === 0 ? 0 : instanceCM.charCoords({line: line, ch: 0}, "local").top;
154
- instanceCM.scrollTo(null, t);
159
+ return true
155
160
  }
156
- return true
157
- }
158
- if (previewEl && previewEl.current) {
161
+ if (previewEl && previewEl.current) {
159
162
  //@ts-ignore
160
- previewEl.current.addEventListener("scroll", listener);
161
- }
162
- return () => {
163
- // @ts-ignore
164
- previewEl && previewEl.current && previewEl && previewEl.current.removeEventListener("scroll", listener);
165
- };
166
- },[text,isPreviewScroll])
163
+ previewEl.current.addEventListener('scroll', listener)
164
+ }
165
+ return () => {
166
+ // @ts-ignore
167
+ previewEl && previewEl.current && previewEl && previewEl.current.removeEventListener('scroll', listener)
168
+ }
169
+ }, [text, isPreviewScroll])
167
170
 
168
- useEffect(() => {
171
+ useEffect(() => {
169
172
  //@ts-ignore
170
173
  let cm = instanceCM
171
- if (!cm) {return}
174
+ if (!cm) {
175
+ return
176
+ }
172
177
  //@ts-ignore
173
178
  marks.forEach(marker => marker.clear())
174
179
  //@ts-ignore
175
- let cmMrks:Array<never> = []
180
+ let cmMrks: Array<never> = []
176
181
  //@ts-ignore
177
- if (result && result.errors ) {
178
-
179
- //@ts-ignore
180
- result.errors.map((loc:any)=>{
181
- // @ts-ignore
182
- let from = {line: loc.start.line-1, ch: loc.start.column-1 - (loc.start.offset === loc.end.offset)};
183
- let to = {line: loc.end.line-1, ch: loc.end.column-1};
182
+ if (result && result.errors) {
183
+ //@ts-ignore
184
+ result.errors.map((loc: any) => {
185
+ // @ts-ignore
186
+ let from = { line: loc.start.line - 1, ch: loc.start.column - 1 - (loc.start.offset === loc.end.offset) }
187
+ let to = { line: loc.end.line - 1, ch: loc.end.column - 1 }
184
188
 
185
- cmMrks.push(
186
- //@ts-ignore
187
- cm.markText(
188
- from,
189
- to,
190
- {
191
- className: 'syntax-error',
192
- title: ';data.error.message',
193
- css: "color : red"
194
- }
195
- )
196
-
197
- )
198
- })
189
+ cmMrks.push(
190
+ //@ts-ignore
191
+ cm.markText(from, to, {
192
+ className: 'syntax-error',
193
+ title: ';data.error.message',
194
+ css: 'color : red',
195
+ }),
196
+ )
197
+ })
199
198
  }
200
199
  updateMarks(cmMrks)
200
+ }, [text, result])
201
201
 
202
- },[text,result])
203
-
204
- const previewHtml = <div className={ "Editorright " + (isDarkTheme ? 'dark' : '' )}
205
- onMouseEnter={()=>setPreviewScrolling(true)}
206
- onMouseMove={()=>setPreviewScrolling(true)}
207
- ref={previewEl}
208
- >
209
- {
210
- result ?
211
- isElement(result.result) ? <div className="content">{result.result}</div> : <div
212
- dangerouslySetInnerHTML={{__html: result.result}}
213
- className="content"
214
- ></div>
215
- : ''
216
-
217
- }
218
- </div>
219
- //@ts-ignore
220
- const scrollEditorHandler = (editor) => {
221
- if (refValue.current) { return }
222
- let scrollInfo = editor.getScrollInfo();
202
+ const previewHtml = (
203
+ <div
204
+ className={'Editorright ' + (isDarkTheme ? 'dark' : '')}
205
+ onMouseEnter={() => setPreviewScrolling(true)}
206
+ onMouseMove={() => setPreviewScrolling(true)}
207
+ ref={previewEl}
208
+ >
209
+ {result ? (
210
+ isElement(result.result) ? (
211
+ <div className="content">{result.result}</div>
212
+ ) : (
213
+ <div dangerouslySetInnerHTML={{ __html: result.result }} className="content"></div>
214
+ )
215
+ ) : (
216
+ ''
217
+ )}
218
+ </div>
219
+ )
220
+ //@ts-ignore
221
+ const scrollEditorHandler = editor => {
222
+ if (refValue.current) {
223
+ return
224
+ }
225
+ let scrollInfo = editor.getScrollInfo()
223
226
  // get line number of the top line in the page
224
- let lineNumber = editor.lineAtHeight(scrollInfo.top, 'local') + 1;
227
+ let lineNumber = editor.lineAtHeight(scrollInfo.top, 'local') + 1
225
228
  if (previewEl) {
226
- const el = previewEl.current
227
- const elementId = `#line-${lineNumber}`
228
- const scrollToElement = document.querySelector(elementId)
229
- if (scrollToElement) {
230
- //@ts-ignore
231
- const scrollTo = scrollToElement.offsetTop
232
- //@ts-ignore
233
- el.scrollTo({
234
- top: scrollTo,
235
- left: 0,
236
- behavior: 'smooth'
237
- })
238
- }
229
+ const el = previewEl.current
230
+ const elementId = `#line-${lineNumber}`
231
+ const scrollToElement = document.querySelector(elementId)
232
+ if (scrollToElement) {
233
+ //@ts-ignore
234
+ const scrollTo = scrollToElement.offsetTop
235
+ //@ts-ignore
236
+ el.scrollTo({
237
+ top: scrollTo,
238
+ left: 0,
239
+ behavior: 'smooth',
240
+ })
241
+ }
239
242
  }
240
- }
241
- const [instanceCMLocal, updateInstanceCM] = useState<any>()
243
+ }
244
+ const [instanceCMLocal, updateInstanceCM] = useState<any>()
242
245
 
243
- useEffect(()=>{
246
+ useEffect(() => {
244
247
  if (!instanceCMLocal) return
245
248
  if (!isAutoComplete) return
246
- var onChange = function(instance, object)
247
- {
248
- // Check if the last inserted character is `=`.
249
- if (object.text[0] === '=' &&
250
- // start directive
251
- instance.getRange({ch:0,line: object.to.line}, object.to).match(/^\s*$/))
252
- {
253
- CMirror.showHint(instanceCMLocal, CMirror.hint.dictionaryHint);
254
- }
255
- }
256
- instanceCMLocal.on('change', onChange);
257
-
258
- CMirror.registerHelper('hint', 'dictionaryHint', function(editor) {
259
- var cur = editor.getCursor();
260
- var curLine = editor.getLine(cur.line);
261
- var start = cur.ch;
262
- var end = start;
263
- while (end < curLine.length && /[\w$]/.test(curLine.charAt(end))) ++end;
264
- while (start && /[^=]/.test(curLine.charAt(start - 1))) --start;
265
- var curWord = start !== end && curLine.slice(start, end);
266
- var regex = new RegExp('' + curWord, 'i');
267
- // filter dict by regex and sort by mostly nearness
268
- const filterDictByRegex = (arr, regex)=>{
269
- const dict = arr.reduce((acc, item)=>{
270
- if (item === null) { return acc; }
271
- const result = (typeof item === 'object' && !Array.isArray(item)) ? item.displayText.match(regex): item.match(regex);
272
- if ( result ) {
273
- acc.push({item, index:result.index})
274
- }
275
- return acc;
276
- }, []);
277
- return dict.sort((a, b) => a.index - b.index).map(i=>i.item)
278
- }
279
- const langMode = sourceType === 'md' ? 'md' : getSuggestionContextForLine(editor.getValue() ,cur.line+1)
280
- const langDict = dictionary.filter( ({lang='pod6'})=>lang === langMode)
281
- // apply hint
282
- const resultDict = (!curWord ? langDict : filterDictByRegex(langDict,regex )).map((item)=>{
283
- return {...item, hint: function(cm,data, completion){
284
- const from = completion.from || data.from
285
- const to = completion.to || data.to
286
- // add vMargin
287
- const text = addVMargin(from.ch, typeof completion == "string" ? completion : completion.text)
288
- const selFromTemplate = templateGetSelectionPos(text)
289
- console.log({from ,to , text})
290
- if (selFromTemplate) {
291
- const {text,start, end} = selFromTemplate
292
- cm.replaceRange(text, from, to, "complete");
293
- cm.setSelection({line: start.line + from.line, ch: start.offset + from.ch}, {line: end.line + to.line, ch: end.offset + to.ch -1});
294
- } else {
295
- cm.replaceRange(text, from, to, "complete");
296
- }
249
+ var onChange = function (instance, object) {
250
+ // Check if the last inserted character is `=`.
251
+ if (
252
+ object.text[0] === '=' &&
253
+ // start directive
254
+ instance.getRange({ ch: 0, line: object.to.line }, object.to).match(/^\s*$/)
255
+ ) {
256
+ CMirror.showHint(instanceCMLocal, CMirror.hint.dictionaryHint)
257
+ }
258
+ }
259
+ instanceCMLocal.on('change', onChange)
297
260
 
298
- }}
299
- })
261
+ CMirror.registerHelper('hint', 'dictionaryHint', function (editor) {
262
+ var cur = editor.getCursor()
263
+ var curLine = editor.getLine(cur.line)
264
+ var start = cur.ch
265
+ var end = start
266
+ while (end < curLine.length && /[\w$]/.test(curLine.charAt(end))) ++end
267
+ while (start && /[^=]/.test(curLine.charAt(start - 1))) --start
268
+ var curWord = start !== end && curLine.slice(start, end)
269
+ var regex = new RegExp('' + curWord, 'i')
270
+ // filter dict by regex and sort by mostly nearness
271
+ const filterDictByRegex = (arr, regex) => {
272
+ const dict = arr.reduce((acc, item) => {
273
+ if (item === null) {
274
+ return acc
275
+ }
276
+ const result =
277
+ typeof item === 'object' && !Array.isArray(item) ? item.displayText.match(regex) : item.match(regex)
278
+ if (result) {
279
+ acc.push({ item, index: result.index })
280
+ }
281
+ return acc
282
+ }, [])
283
+ return dict.sort((a, b) => a.index - b.index).map(i => i.item)
284
+ }
285
+ const langMode = sourceType === 'md' ? 'md' : getSuggestionContextForLine(editor.getValue(), cur.line + 1)
286
+ const langDict = dictionary.filter(({ lang = 'pod6' }) => lang === langMode)
287
+ // apply hint
288
+ const resultDict = (!curWord ? langDict : filterDictByRegex(langDict, regex)).map(item => {
300
289
  return {
301
- list: resultDict,
302
- from: CMirror.Pos(cur.line, start-1),
303
- to: CMirror.Pos(cur.line, end)
290
+ ...item,
291
+ hint: function (cm, data, completion) {
292
+ const from = completion.from || data.from
293
+ const to = completion.to || data.to
294
+ // add vMargin
295
+ const text = addVMargin(from.ch, typeof completion == 'string' ? completion : completion.text)
296
+ const selFromTemplate = templateGetSelectionPos(text)
297
+ console.log({ from, to, text })
298
+ if (selFromTemplate) {
299
+ const { text, start, end } = selFromTemplate
300
+ cm.replaceRange(text, from, to, 'complete')
301
+ cm.setSelection(
302
+ { line: start.line + from.line, ch: start.offset + from.ch },
303
+ { line: end.line + to.line, ch: end.offset + to.ch - 1 },
304
+ )
305
+ } else {
306
+ cm.replaceRange(text, from, to, 'complete')
307
+ }
308
+ },
304
309
  }
305
- });
310
+ })
311
+ return {
312
+ list: resultDict,
313
+ from: CMirror.Pos(cur.line, start - 1),
314
+ to: CMirror.Pos(cur.line, end),
315
+ }
316
+ })
306
317
  instanceCMLocal.refresh()
307
318
  return () => {
308
- //@ts-ignore
309
- instanceCMLocal.off('change', onChange)
319
+ //@ts-ignore
320
+ instanceCMLocal.off('change', onChange)
310
321
  }
311
- },[instanceCMLocal, isAutoComplete])
322
+ }, [instanceCMLocal, isAutoComplete])
312
323
 
313
- return (
314
- <div className="EditorApp">
315
- <div className={ isPreviewModeEnabled ? "layoutPreview": "layout"}>
316
- <div className="Editorleft" onMouseEnter={()=>setPreviewScrolling(false)}
317
- onMouseMove={()=>setPreviewScrolling(false)}
324
+ return (
325
+ <div className="EditorApp">
326
+ <div className={isPreviewModeEnabled ? 'layoutPreview' : 'layout'}>
327
+ <div
328
+ className="Editorleft"
329
+ onMouseEnter={() => setPreviewScrolling(false)}
330
+ onMouseMove={() => setPreviewScrolling(false)}
318
331
  >
319
- {isControlled ?
332
+ {isControlled ? (
320
333
  <CodeMirrorControlled
321
- value={content}
322
- editorDidMount={ editor => { instanceCM = editor; updateInstanceCM(editor) } }
323
- onBeforeChange={(editor, data, value) => {
324
- setChanged(true);
334
+ value={content}
335
+ editorDidMount={editor => {
336
+ instanceCM = editor
337
+ updateInstanceCM(editor)
338
+ }}
339
+ onBeforeChange={(editor, data, value) => {
340
+ setChanged(true)
325
341
  // updateText(value);
326
342
  onChangeSource(value)
327
- }}
328
- onScroll={scrollEditorHandler}
329
- options={options}
330
- className="editorApp"
343
+ }}
344
+ onScroll={scrollEditorHandler}
345
+ options={options}
346
+ className="editorApp"
331
347
  />
332
- :
333
- <CodeMirror
334
- value={content}
335
- editorDidMount={ editor => { instanceCM = editor; updateInstanceCM(editor) } }
336
- onChange = { (editor, data, value) => {
337
- setChanged(true);
338
- updateText(value);
339
- onChangeSource(value)
340
- } }
341
- onScroll={scrollEditorHandler}
342
- options={options}
343
- className="editorApp"
348
+ ) : (
349
+ <CodeMirror
350
+ value={content}
351
+ editorDidMount={editor => {
352
+ instanceCM = editor
353
+ updateInstanceCM(editor)
354
+ }}
355
+ onChange={(editor, data, value) => {
356
+ setChanged(true)
357
+ updateText(value)
358
+ onChangeSource(value)
359
+ }}
360
+ onScroll={scrollEditorHandler}
361
+ options={options}
362
+ className="editorApp"
344
363
  />
345
- }
346
- </div>
347
- {previewHtml}
364
+ )}
365
+ </div>
366
+ {previewHtml}
367
+ </div>
348
368
  </div>
349
- </div>
350
- );
369
+ )
351
370
  }
371
+
372
+ export default Editor
package/esm/dict.d.ts DELETED
@@ -1,7 +0,0 @@
1
- interface Dict {
2
- displayText: string;
3
- text: string;
4
- lang?: 'pod6' | 'md';
5
- }
6
- declare const dict: Dict[];
7
- export default dict;
package/esm/helpers.d.ts DELETED
@@ -1,15 +0,0 @@
1
- import { PodliteDocument } from '@podlite/schema';
2
- export declare const parse: (str: string) => PodliteDocument;
3
- export declare const getSuggestionContextForLine: (pod: string, line: number) => 'pod6' | 'md';
4
- interface Pos {
5
- line: number;
6
- offset: number;
7
- }
8
- interface Selection {
9
- start: Pos;
10
- end: Pos;
11
- text?: string;
12
- }
13
- export declare const templateGetSelectionPos: (pod: string) => Selection | null;
14
- export declare const addVMargin: (count: number, pod: string) => string;
15
- export {};