mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 03:25:11 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			77 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import type {FileRenderPlugin} from '../render/plugin.ts';
 | |
| import {newRenderPlugin3DViewer} from '../render/plugins/3d-viewer.ts';
 | |
| import {newRenderPluginPdfViewer} from '../render/plugins/pdf-viewer.ts';
 | |
| import {registerGlobalInitFunc} from '../modules/observer.ts';
 | |
| import {createElementFromHTML, showElem, toggleClass} from '../utils/dom.ts';
 | |
| import {html} from '../utils/html.ts';
 | |
| import {basename} from '../utils.ts';
 | |
| 
 | |
| const plugins: FileRenderPlugin[] = [];
 | |
| 
 | |
| function initPluginsOnce(): void {
 | |
|   if (plugins.length) return;
 | |
|   plugins.push(newRenderPlugin3DViewer(), newRenderPluginPdfViewer());
 | |
| }
 | |
| 
 | |
| function findFileRenderPlugin(filename: string, mimeType: string): FileRenderPlugin | null {
 | |
|   return plugins.find((plugin) => plugin.canHandle(filename, mimeType)) || null;
 | |
| }
 | |
| 
 | |
| function showRenderRawFileButton(elFileView: HTMLElement, renderContainer: HTMLElement | null): void {
 | |
|   const toggleButtons = elFileView.querySelector('.file-view-toggle-buttons');
 | |
|   showElem(toggleButtons);
 | |
|   const displayingRendered = Boolean(renderContainer);
 | |
|   toggleClass(toggleButtons.querySelectorAll('.file-view-toggle-source'), 'active', !displayingRendered); // it may not exist
 | |
|   toggleClass(toggleButtons.querySelector('.file-view-toggle-rendered'), 'active', displayingRendered);
 | |
|   // TODO: if there is only one button, hide it?
 | |
| }
 | |
| 
 | |
| async function renderRawFileToContainer(container: HTMLElement, rawFileLink: string, mimeType: string) {
 | |
|   const elViewRawPrompt = container.querySelector('.file-view-raw-prompt');
 | |
|   if (!rawFileLink || !elViewRawPrompt) throw new Error('unexpected file view container');
 | |
| 
 | |
|   let rendered = false, errorMsg = '';
 | |
|   try {
 | |
|     const plugin = findFileRenderPlugin(basename(rawFileLink), mimeType);
 | |
|     if (plugin) {
 | |
|       container.classList.add('is-loading');
 | |
|       container.setAttribute('data-render-name', plugin.name); // not used yet
 | |
|       await plugin.render(container, rawFileLink);
 | |
|       rendered = true;
 | |
|     }
 | |
|   } catch (e) {
 | |
|     errorMsg = `${e}`;
 | |
|   } finally {
 | |
|     container.classList.remove('is-loading');
 | |
|   }
 | |
| 
 | |
|   if (rendered) {
 | |
|     elViewRawPrompt.remove();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // remove all children from the container, and only show the raw file link
 | |
|   container.replaceChildren(elViewRawPrompt);
 | |
| 
 | |
|   if (errorMsg) {
 | |
|     const elErrorMessage = createElementFromHTML(html`<div class="ui error message">${errorMsg}</div>`);
 | |
|     elViewRawPrompt.insertAdjacentElement('afterbegin', elErrorMessage);
 | |
|   }
 | |
| }
 | |
| 
 | |
| export function initRepoFileView(): void {
 | |
|   registerGlobalInitFunc('initRepoFileView', async (elFileView: HTMLElement) => {
 | |
|     initPluginsOnce();
 | |
|     const rawFileLink = elFileView.getAttribute('data-raw-file-link');
 | |
|     const mimeType = elFileView.getAttribute('data-mime-type') || ''; // not used yet
 | |
|     // TODO: we should also provide the prefetched file head bytes to let the plugin decide whether to render or not
 | |
|     const plugin = findFileRenderPlugin(basename(rawFileLink), mimeType);
 | |
|     if (!plugin) return;
 | |
| 
 | |
|     const renderContainer = elFileView.querySelector<HTMLElement>('.file-view-render-container');
 | |
|     showRenderRawFileButton(elFileView, renderContainer);
 | |
|     // maybe in the future multiple plugins can render the same file, so we should not assume only one plugin will render it
 | |
|     if (renderContainer) await renderRawFileToContainer(renderContainer, rawFileLink, mimeType);
 | |
|   });
 | |
| }
 |