import { attributesHtml } from './htmlUtils'; import { ItemIdToUrlHandler, OptionsResourceModel } from './types'; const Entities = require('html-entities').AllHtmlEntities; const htmlentities = new Entities().encode; // Imported from models/Resource.js const FetchStatuses = { FETCH_STATUS_IDLE: 0, FETCH_STATUS_STARTED: 1, FETCH_STATUS_DONE: 2, FETCH_STATUS_ERROR: 3, }; export const getAttr = function(attrs: string[], name: string, defaultValue: string = null) { for (let i = 0; i < attrs.length; i++) { if (attrs[i][0] === name) return attrs[i].length > 1 ? attrs[i][1] : null; } return defaultValue; }; export const notDownloadedResource = function() { return ` `; }; export const notDownloadedImage = function() { // https://github.com/ForkAwesome/Fork-Awesome/blob/master/src/icons/svg/file-image-o.svg // Height changed to 1795 return ` `; }; export const notDownloadedFile = function() { // https://github.com/ForkAwesome/Fork-Awesome/blob/master/src/icons/svg/file-o.svg return ` `; }; export const errorImage = function() { // https://github.com/ForkAwesome/Fork-Awesome/blob/master/src/icons/svg/times-circle.svg return ` `; }; export const loaderImage = function() { // https://github.com/ForkAwesome/Fork-Awesome/blob/master/src/icons/svg/hourglass-half.svg return ` `; }; export const resourceStatusImage = function(status: string) { if (status === 'notDownloaded') return notDownloadedResource(); return resourceStatusFile(status); }; export const resourceStatusFile = function(status: string) { if (status === 'notDownloaded') return notDownloadedResource(); if (status === 'downloading') return loaderImage(); if (status === 'encrypted') return loaderImage(); if (status === 'error') return errorImage(); throw new Error(`Unknown status: ${status}`); }; export const resourceStatusIndex = function(status: string) { if (status === 'error') return -1; if (status === 'notDownloaded') return 0; if (status === 'downloading') return 1; if (status === 'encrypted') return 2; if (status === 'ready') return 10; throw new Error(`Unknown status: ${status}`); }; export const resourceStatusName = function(index: number) { if (index === -1) return 'error'; if (index === 0) return 'notDownloaded'; if (index === 1) return 'downloading'; if (index === 2) return 'encrypted'; if (index === 10) return 'ready'; throw new Error(`Unknown index: ${index}`); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied export const resourceStatus = function(ResourceModel: OptionsResourceModel, resourceInfo: any) { if (!ResourceModel) return 'ready'; let status = 'ready'; if (resourceInfo) { const resource = resourceInfo.item; const localState = resourceInfo.localState; if (localState.fetch_status === FetchStatuses.FETCH_STATUS_IDLE) { status = 'notDownloaded'; } else if (localState.fetch_status === FetchStatuses.FETCH_STATUS_STARTED) { status = 'downloading'; } else if (localState.fetch_status === FetchStatuses.FETCH_STATUS_DONE) { if (resource.encryption_blob_encrypted || resource.encryption_applied) { status = 'encrypted'; } } } else { status = 'notDownloaded'; } return status; }; type ImageMarkupData = { src: string; alt: string; title: string; }|{ src: string; before: string; after: string }; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied export const imageReplacement = function(ResourceModel: OptionsResourceModel, markup: ImageMarkupData, resources: any, resourceBaseUrl: string, itemIdToUrl: ItemIdToUrlHandler = null) { if (!ResourceModel || !resources) return null; const src = markup.src; if (!ResourceModel.isResourceUrl(src)) return null; const resourceId = ResourceModel.urlToId(src); const result = resources[resourceId]; const resource = result ? result.item : null; const status = resourceStatus(ResourceModel, result); if (status !== 'ready') { const icon = resourceStatusImage(status); // Preserve information necessary to restore the original markup when converting // from HTML to markdown. const attrs: Record = { class: `not-loaded-resource not-loaded-image-resource resource-status-${status}`, ['data-resource-id']: resourceId, }; if ('alt' in markup) { attrs['data-original-alt'] = markup.alt; attrs['data-original-title'] = markup.title; } else { attrs['data-original-before'] = markup.before; attrs['data-original-after'] = markup.after; } // contenteditable="false": Improves support for the Rich Text Editor -- without this, // users can add content within the
, which breaks the html-to-md conversion. return ( `
` + `` + '
' ); } const mime = resource.mime ? resource.mime.toLowerCase() : ''; if (ResourceModel.isSupportedImageMimeType(mime)) { let newSrc = ''; const timestampParameter = `?t=${resource.updated_time}`; const idToUrlResult = itemIdToUrl?.(resource.id, timestampParameter) ?? null; if (idToUrlResult !== null) { newSrc = idToUrlResult; } else { const temp = []; if (resourceBaseUrl) { temp.push(resourceBaseUrl); } else { temp.push('./'); } temp.push(ResourceModel.filename(resource)); temp.push(timestampParameter); newSrc = temp.join(''); } // let newSrc = `./${ResourceModel.filename(resource)}`; // newSrc += `?t=${resource.updated_time}`; return { 'data-resource-id': resource.id, src: newSrc, }; } return null; }; // Used in mobile app when enableLongPress = true. Tells for how long // the resource should be pressed before the menu is shown. export const longPressDelay = 500;