feat: Initial clean release of CHM
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
这个提交包含在:
@@ -0,0 +1,115 @@
|
||||
import { Link } from '../MdToHtml';
|
||||
import { toForwardSlashes } from '@joplin/utils/path';
|
||||
import { LinkIndexes } from './rules/link_close';
|
||||
import { RendererTheme } from '../types';
|
||||
import { AllHtmlEntities as Entities } from 'html-entities';
|
||||
const htmlentities = new Entities().encode;
|
||||
|
||||
export interface Options {
|
||||
audioPlayerEnabled: boolean;
|
||||
videoPlayerEnabled: boolean;
|
||||
autoplayVideo?: boolean;
|
||||
pdfViewerEnabled: boolean;
|
||||
useCustomPdfViewer: boolean;
|
||||
noteId: string;
|
||||
vendorDir: string;
|
||||
theme: RendererTheme;
|
||||
}
|
||||
|
||||
function resourceUrl(resourceFullPath: string): string {
|
||||
if (
|
||||
resourceFullPath.indexOf('http://') === 0 || resourceFullPath.indexOf('https://') === 0 || resourceFullPath.indexOf('joplin-content://') === 0 ||
|
||||
resourceFullPath.indexOf('file://') === 0 ||
|
||||
// On web, resources are loaded as blob URLs.
|
||||
resourceFullPath.startsWith('blob:null/')
|
||||
) {
|
||||
return resourceFullPath;
|
||||
}
|
||||
return `file://${toForwardSlashes(resourceFullPath)}`;
|
||||
}
|
||||
|
||||
const resourceHash = (link: string) => {
|
||||
// Preserve certain #hash strings when rendering resources.
|
||||
// These patterns can be used to customize the starting/ending points for
|
||||
// audio/video/PDF embeds:
|
||||
const patterns = [
|
||||
// Starting PDF page
|
||||
/#page=\d+$/,
|
||||
// Staring/ending playback time
|
||||
/#t=[0-9:,]+$/,
|
||||
];
|
||||
|
||||
for (const pattern of patterns) {
|
||||
const match = link.match(pattern);
|
||||
if (match) {
|
||||
return match[0];
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
export default function(link: Link, options: Options, linkIndexes: LinkIndexes) {
|
||||
const resource = link.resource;
|
||||
|
||||
if (!link.resourceReady || !resource || !resource.mime) return '';
|
||||
|
||||
const escapedResourcePath = htmlentities(
|
||||
resourceUrl(link.resourceFullPath) + resourceHash(link.href),
|
||||
);
|
||||
const escapedMime = htmlentities(resource.mime);
|
||||
const escapedTitle = htmlentities(resource.title || resource.mime);
|
||||
const resourceIdAttribute = resource.id ? ` data-resource-id="${htmlentities(resource.id)}"` : '';
|
||||
|
||||
if (options.videoPlayerEnabled && resource.mime.indexOf('video/') === 0) {
|
||||
const playbackAttributes = options.autoplayVideo ? 'autoplay muted playsinline preload="auto"' : 'preload="metadata"';
|
||||
return `
|
||||
<video class="media-player media-video" controls${resourceIdAttribute} ${playbackAttributes} aria-label="${escapedTitle}">
|
||||
<source src="${escapedResourcePath}" type="${escapedMime}">
|
||||
</video>
|
||||
`;
|
||||
}
|
||||
|
||||
if (options.audioPlayerEnabled && resource.mime.indexOf('audio/') === 0) {
|
||||
// We want to support both audio/x-flac and audio/flac MIME types, but chromium only supports audio/flac
|
||||
// https://github.com/laurent22/joplin/issues/6434
|
||||
const escapedAudioMime = escapedMime === 'audio/x-flac' ? 'audio/flac' : escapedMime;
|
||||
return `
|
||||
<audio class="media-player media-audio" controls preload="metadata" aria-label="${escapedTitle}">
|
||||
<source src="${escapedResourcePath}" type="${escapedAudioMime}">
|
||||
</audio>
|
||||
`;
|
||||
}
|
||||
|
||||
if (options.pdfViewerEnabled && resource.mime === 'application/pdf') {
|
||||
|
||||
if (options.useCustomPdfViewer) {
|
||||
const resourceId = resource.id;
|
||||
let anchorPageNo = null;
|
||||
|
||||
let id = `${options.noteId}.${resourceId}`;
|
||||
if (linkIndexes && linkIndexes[resourceId]) {
|
||||
linkIndexes[resourceId]++;
|
||||
} else {
|
||||
linkIndexes[resourceId] = 1;
|
||||
}
|
||||
id += `.${linkIndexes[resourceId]}`;
|
||||
|
||||
if (link.href.indexOf('#') > 0) {
|
||||
anchorPageNo = Number(link.href.split('#').pop());
|
||||
if (anchorPageNo < 1) anchorPageNo = null;
|
||||
}
|
||||
|
||||
const src = `${options.vendorDir}/lib/@joplin/pdf-viewer/index.html`;
|
||||
|
||||
return `<iframe src="${src}" x-url="${escapedResourcePath}"
|
||||
x-appearance="${options.theme.appearance}" ${anchorPageNo ? `x-anchorPage="${anchorPageNo}"` : ''} id="${id}"
|
||||
x-type="mini" x-resourceid="${resourceId}"
|
||||
class="media-player media-pdf"></iframe>`;
|
||||
}
|
||||
|
||||
return `<object data="${escapedResourcePath}" class="media-player media-pdf" type="${escapedMime}"></object>`;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户