All checks were successful
		
		
	
	Build Tilde Friends / Build-All (push) Successful in 32m4s
				
			
		
			
				
	
	
		
			142 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import * as hashtagify from './commonmark-hashtag.js';
 | 
						|
 | 
						|
const k_code_classes = 'w3-theme-l4 w3-theme-border w3-round';
 | 
						|
 | 
						|
var reUnsafeProtocol = /^javascript:|vbscript:|file:|data:/i;
 | 
						|
var reSafeDataProtocol = /^data:image\/(?:png|gif|jpeg|webp)/i;
 | 
						|
var potentiallyUnsafe = function (url) {
 | 
						|
	return reUnsafeProtocol.test(url) && !reSafeDataProtocol.test(url);
 | 
						|
};
 | 
						|
 | 
						|
function image(node, entering) {
 | 
						|
	if (
 | 
						|
		node.firstChild?.type === 'text' &&
 | 
						|
		node.firstChild.literal.startsWith('video:')
 | 
						|
	) {
 | 
						|
		if (entering) {
 | 
						|
			this.lit(
 | 
						|
				'<video style="max-width: 100%; max-height: 480px" title="' +
 | 
						|
					this.esc(node.firstChild?.literal) +
 | 
						|
					'" controls>'
 | 
						|
			);
 | 
						|
			this.lit('<source src="' + this.esc(node.destination) + '"></source>');
 | 
						|
			this.disableTags += 1;
 | 
						|
		} else {
 | 
						|
			this.disableTags -= 1;
 | 
						|
			this.lit('</video>');
 | 
						|
		}
 | 
						|
	} else if (
 | 
						|
		node.firstChild?.type === 'text' &&
 | 
						|
		node.firstChild.literal.startsWith('audio:')
 | 
						|
	) {
 | 
						|
		if (entering) {
 | 
						|
			this.lit(
 | 
						|
				'<audio style="height: 32px; max-width: 100%" title="' +
 | 
						|
					this.esc(node.firstChild?.literal) +
 | 
						|
					'" controls>'
 | 
						|
			);
 | 
						|
			this.lit('<source src="' + this.esc(node.destination) + '"></source>');
 | 
						|
			this.disableTags += 1;
 | 
						|
		} else {
 | 
						|
			this.disableTags -= 1;
 | 
						|
			this.lit('</audio>');
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if (entering) {
 | 
						|
			if (this.disableTags === 0) {
 | 
						|
				this.lit(
 | 
						|
					'<div class="img_caption">' +
 | 
						|
						this.esc(node.firstChild?.literal || node.destination) +
 | 
						|
						'</div>'
 | 
						|
				);
 | 
						|
				if (this.options.safe && potentiallyUnsafe(node.destination)) {
 | 
						|
					this.lit('<img src="" title="');
 | 
						|
				} else {
 | 
						|
					this.lit('<img src="' + this.esc(node.destination) + '" title="');
 | 
						|
				}
 | 
						|
			}
 | 
						|
			this.disableTags += 1;
 | 
						|
		} else {
 | 
						|
			this.disableTags -= 1;
 | 
						|
			if (this.disableTags === 0) {
 | 
						|
				if (node.title) {
 | 
						|
					this.lit('" title="' + this.esc(node.title));
 | 
						|
				}
 | 
						|
				this.lit('" />');
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
function code(node) {
 | 
						|
	let attrs = this.attrs(node);
 | 
						|
	attrs.push(['class', k_code_classes]);
 | 
						|
	this.tag('code', attrs);
 | 
						|
	this.out(node.literal);
 | 
						|
	this.tag('/code');
 | 
						|
}
 | 
						|
 | 
						|
function attrs(node) {
 | 
						|
	let result = commonmark.HtmlRenderer.prototype.attrs.bind(this)(node);
 | 
						|
	if (node.type == 'block_quote') {
 | 
						|
		result.push(['class', 'w3-theme-d1']);
 | 
						|
	} else if (node.type == 'code_block') {
 | 
						|
		result.push(['class', k_code_classes]);
 | 
						|
	}
 | 
						|
	return result;
 | 
						|
}
 | 
						|
 | 
						|
export function markdown(md) {
 | 
						|
	let reader = new commonmark.Parser();
 | 
						|
	let writer = new commonmark.HtmlRenderer({safe: true});
 | 
						|
	writer.image = image;
 | 
						|
	writer.code = code;
 | 
						|
	writer.attrs = attrs;
 | 
						|
	let parsed = reader.parse(md || '');
 | 
						|
	parsed = hashtagify.transform(parsed);
 | 
						|
	let walker = parsed.walker();
 | 
						|
	let event, node;
 | 
						|
	while ((event = walker.next())) {
 | 
						|
		node = event.node;
 | 
						|
		if (event.entering) {
 | 
						|
			if (node.type == 'link') {
 | 
						|
				if (
 | 
						|
					node.destination.startsWith('@') &&
 | 
						|
					node.destination.endsWith('.ed25519')
 | 
						|
				) {
 | 
						|
					node.destination = '#' + encodeURIComponent(node.destination);
 | 
						|
				} else if (
 | 
						|
					node.destination.startsWith('%') &&
 | 
						|
					node.destination.endsWith('.sha256')
 | 
						|
				) {
 | 
						|
					node.destination = '#' + encodeURIComponent(node.destination);
 | 
						|
				} else if (
 | 
						|
					node.destination.startsWith('&') &&
 | 
						|
					node.destination.endsWith('.sha256')
 | 
						|
				) {
 | 
						|
					node.destination = '/' + node.destination + '/view';
 | 
						|
				}
 | 
						|
			} else if (node.type == 'image') {
 | 
						|
				if (node.destination.startsWith('&')) {
 | 
						|
					node.destination = '/' + node.destination + '/view';
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return writer.render(parsed);
 | 
						|
}
 | 
						|
 | 
						|
export function human_readable_size(bytes) {
 | 
						|
	let v = bytes;
 | 
						|
	let u = 'B';
 | 
						|
	for (let unit of ['kB', 'MB', 'GB']) {
 | 
						|
		if (v > 1024) {
 | 
						|
			v /= 1024;
 | 
						|
			u = unit;
 | 
						|
		} else {
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return `${Math.round(v * 10) / 10} ${u}`;
 | 
						|
}
 |