PageSourceSearch

https://visitrunavik.fo/views/whatson/views/js/MarkdownHandler.js?v=1790869110

js visitrunavik.fo collected 2026-10-02 22:55:06 UTC 6,428 bytes, 216 lines download raw bytes

1
2/**
3 * Markdown handler
4 * 
5 * Handles content with markdown
6 * 
7 * @author 					Pætur Mortensen
8 */
9class MarkdownHandler{
10
11	// The processed output
12	output;
13	// Markdown markers on the system
14	markers = {
15		image: { markdown: '#image#', methodName: 'process_image_markdown' },
16		bold: { markdown: '#bold#', methodName: 'process_bold_markdown' },
17		italic: { markdown: '#italic#', methodName: 'process_italic_markdown' },
18	};
19	// Currently handled markdown instance
20	currentMarkdown = { type: null, startPosition: 0, endPosition: 0 };
21
22	constructor(input){
23		// Set the initial output as the input
24		this.output = input;
25		
26		// Handle all markdown
27		this.handle_markdown();
28	}
29
30	/**
31	 * Handle all markdown in the content
32	 * 
33	 * @author 					Pætur Mortensen
34	 */
35	handle_markdown(){
36
37		// For each type of markdown marker
38		for(const type in this.markers){
39			const marker = this.markers[type];
40			// Set the marker type currently being worked
41			this.currentMarkdown.type = type;
42			// Extract markdown identifier and method name from the marker
43			const markdown = marker.markdown;
44			const methodName = marker.methodName;
45
46			// Find position of marker if set and set as currently worked markdown
47			this.currentMarkdown.startPosition = this.output.indexOf(markdown);
48
49			// While there is an instance of the markdown marker, process it
50			while(this.currentMarkdown.startPosition !== -1){
51				// Call the marker method for this type of marker and get the string for injection
52				const injectString = this[methodName]();
53
54				// Inject the formatted string if there is one to inject
55				if(injectString) this.inject_formatted_string(injectString);
56				// There is no injection string, clear the marker so we don't end up with infinite loop
57				else this.clear_markdown_marker();
58
59				// Once the above marker has been processed, search again to see if there are more
60				this.currentMarkdown.startPosition = this.output.indexOf(markdown);
61			}
62		}
63	}
64
65	/**
66	 * Inject the formatted string in place of the markdown
67	 * 
68	 * @param 		{string} 	injectString 										String to inject in place of markdown
69	 * 
70	 * @author 					Pætur Mortensen
71	 */
72	inject_formatted_string(injectString){
73		// Get strings before and after the markdown
74		const beforeString = this.output.substring(0, this.currentMarkdown.startPosition);
75		const afterString = this.output.substring(this.currentMarkdown.endPosition + 1);
76		// Build new output with formatted markdown
77		this.output = beforeString + injectString + afterString;
78	}
79
80	/**
81	 * Get the content from the markdown
82	 * 
83	 * @author 					Pætur Mortensen
84	 */
85	get_markdown_content()
86	{
87		// Set the type for this markdown
88		const type = this.currentMarkdown.type;
89		// Identify the marker itself and set string positions for it
90		const marker = this.markers[type].markdown;
91		const markerLength = marker.length;
92		// Set the marker end position
93		const markerEndPos = this.currentMarkdown.startPosition + markerLength;
94		
95		// Get the delimiter positions (delimiters for the markdown content)
96		const delimiterPositions = this.get_delimiter_positions(markerEndPos);
97
98		// If delimiters were not found, return NULL
99		if(!delimiterPositions) return null;
100
101		// Extract the content from the output
102		const content = this.output.substring(delimiterPositions.start + 1, delimiterPositions.end);
103
104		// If there is no content, just return null
105		if(!content) return null;
106
107		return content;
108	}
109
110	/**
111	 * Get the delimiter positions
112	 * 
113	 * @author 						Pætur Mortensen
114	 */
115	get_delimiter_positions(startPosition)
116	{
117		// If the delimiter is not found here, return FALSE
118		if(this.output[startPosition] !== '(') return false;
119		// Get the position for the end delimiter
120		const endPosition = this.output.indexOf(')', startPosition);
121
122		// If no end position was found, return FALSE
123		if(!endPosition) return false;
124
125		// Set the current markdown end position
126		this.currentMarkdown.endPosition = endPosition;
127
128		// Return start and end delimiter positions
129		return {start: startPosition, end: endPosition};
130	}
131
132	/**
133	 * Clear the first instance of the current markdown marker
134	 * 
135	 * This is done to ensure this marker isn't identified again and we get an infinite loop when 
136	 * there is some issue with the markdown
137	 * 
138	 * @author 					Pætur Mortensen
139	 */
140	clear_markdown_marker()
141	{
142		// Get the current type and the markdown for it
143		const type = this.currentMarkdown.type;
144		const marker = this.markers[type].markdown;
145		// Find the first instance of the marker in the string
146		const position = this.output.indexOf(marker);
147		// Find the end position for the marker by its length
148		const markerEndPos = position + marker.length;
149
150		// Now remove the marker from the string
151		this.output = this.output.substring(0, position) + this.output.substring(markerEndPos);
152	}
153
154/***************************************************************************************************
155 * 
156 * 																	MARKDOWN PROCESSORS
157 * 
158 **************************************************************************************************/
159
160	/**
161	 * Process markdown for an image #image#()
162	 * 
163	 * @author 					Pætur Mortensen
164	 */
165	process_image_markdown(){
166		// Get the image source from the markdown content
167		const imgSrc = this.get_markdown_content();
168	
169		// Image source not found. Return NULL for cleanup
170		if(!imgSrc) return null;
171	
172		// Build the string to inject in place of the markdown
173		 return '<img src="' + imgSrc + '" alt="markdown image" class="markdown-image" />';
174	}
175
176	/**
177	 * Process markdown for bold text #bold#()
178	 * 
179	 * @author 					Pætur Mortensen
180	 */
181	process_bold_markdown(){
182		// Get the content from the markdown content
183		const content = this.get_markdown_content();
184	
185		// Content not found. Return NULL for cleanup
186		if(!content) return null;
187	
188		// Build the string to inject in place of the markdown
189		 return '<b>' + content + '</b>';
190	}
191
192	/**
193	 * Process markdown for italic text #italic#()
194	 * 
195	 * @author 					Pætur Mortensen
196	 */
197	process_italic_markdown(){
198		// Get the content from the markdown content
199		const content = this.get_markdown_content();
200	
201		// Content not found. Return NULL for cleanup
202		if(!content) return null;
203	
204		// Build the string to inject in place of the markdown
205		 return '<i>' + content + '</i>';
206	}
207
208	/**
209	 * Return the formatted result
210	 * 
211	 * @author 						Pætur Mortensen
212	 */
213	result(){
214		return this.output;
215	}
216}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.