()
| 949 | } |
| 950 | |
| 951 | toMarkdown() { |
| 952 | if(this._md) return this._md; |
| 953 | |
| 954 | let cm = this.cm; |
| 955 | let doc = cm.getDoc(); |
| 956 | let spans = this.getAllSpans(); |
| 957 | let fullText = cm.getValue(); |
| 958 | let markers:{pos: number, start?:boolean, isBlock?:boolean, isLine?:boolean, source:any, span?:Span}[] = []; |
| 959 | for(let span of spans) { |
| 960 | let loc = span.find(); |
| 961 | if(!loc) continue; |
| 962 | markers.push({pos: doc.indexFromPos(loc.from), start: true, isBlock: span.isBlock(), isLine: span.isLine(), source: span.source, span}); |
| 963 | markers.push({pos: doc.indexFromPos(loc.to), start: false, isBlock: span.isBlock(), isLine: span.isLine(), source: span.source, span}); |
| 964 | } |
| 965 | markers.sort((a, b) => { |
| 966 | let delta = a.pos - b.pos; |
| 967 | if(delta !== 0) return delta; |
| 968 | if(a.isBlock && !b.isBlock) return -1; |
| 969 | if(b.isBlock && !a.isBlock) return 1; |
| 970 | if(a.isLine && !b.isLine) return -1; |
| 971 | if(b.isLine && !a.isLine) return 1; |
| 972 | if(a.start && !b.start) return 1; |
| 973 | if(b.start && !a.start) return -1; |
| 974 | if(a.source.type === b.source.type) return 0; |
| 975 | else if(a.source.type === "link") return a.start ? 1 : -1; |
| 976 | else if(b.source.type === "link") return b.start ? -1 : 1; |
| 977 | return 0; |
| 978 | }); |
| 979 | |
| 980 | let pos = 0; |
| 981 | let pieces:string[] = []; |
| 982 | for(let mark of markers) { |
| 983 | if(!mark.source) continue; |
| 984 | |
| 985 | // If the cursor isn't at this mark yet, push the range between and advance the cursor. |
| 986 | if(pos !== mark.pos) { |
| 987 | pieces.push(fullText.substring(pos, mark.pos)); |
| 988 | pos = mark.pos; |
| 989 | } |
| 990 | |
| 991 | // Break each known span type out into its markdown equivalent. |
| 992 | let type = mark.source.type; |
| 993 | if(type === "heading" && mark.start) { |
| 994 | for(let ix = 0; ix < mark.source.level; ix++) { |
| 995 | pieces.push("#"); |
| 996 | } |
| 997 | pieces.push(" "); |
| 998 | } else if(type == "link" && !mark.start) { |
| 999 | pieces.push(`](${mark.source.destination})`); |
| 1000 | } else if(type === "emph") { |
| 1001 | pieces.push("*"); |
| 1002 | } else if(type == "strong") { |
| 1003 | pieces.push("**"); |
| 1004 | } else if(type == "code") { |
| 1005 | pieces.push("`"); |
| 1006 | } else if(type == "code_block" && mark.start) { |
| 1007 | pieces.push("```" + (mark.source.info || "") + "\n"); |
| 1008 |
no test coverage detected