189 lines
5.2 KiB
JavaScript
189 lines
5.2 KiB
JavaScript
const ALLOWED_TARGET_PATHS = new Set(['/works/detail']);
|
|
const SHARE_TARGET_MESSAGE_TYPE = 'genarrative:share-target';
|
|
const WEB_VIEW_SHARE_PATH = '/pages/web-view/index';
|
|
|
|
function trimTrailingSlash(value) {
|
|
return String(value || '').trim().replace(/\/+$/u, '');
|
|
}
|
|
|
|
function appendQuery(url, query) {
|
|
const rawUrl = String(url || '');
|
|
const pairs = Object.keys(query)
|
|
.filter((key) => query[key])
|
|
.map(
|
|
(key) =>
|
|
`${encodeURIComponent(key)}=${encodeURIComponent(String(query[key]))}`,
|
|
);
|
|
|
|
if (pairs.length === 0) {
|
|
return rawUrl;
|
|
}
|
|
|
|
const hashIndex = rawUrl.indexOf('#');
|
|
const baseUrl = hashIndex >= 0 ? rawUrl.slice(0, hashIndex) : rawUrl;
|
|
const hash = hashIndex >= 0 ? rawUrl.slice(hashIndex) : '';
|
|
return `${baseUrl}${baseUrl.includes('?') ? '&' : '?'}${pairs.join('&')}${hash}`;
|
|
}
|
|
|
|
function appendHashParams(url, params) {
|
|
const nextKeys = new Set(Object.keys(params).filter((key) => params[key]));
|
|
const pairs = Object.keys(params)
|
|
.filter((key) => params[key])
|
|
.map(
|
|
(key) =>
|
|
`${encodeURIComponent(key)}=${encodeURIComponent(String(params[key]))}`,
|
|
);
|
|
if (pairs.length === 0) {
|
|
return url;
|
|
}
|
|
|
|
const hashIndex = url.indexOf('#');
|
|
const baseUrl = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
const rawHash = hashIndex >= 0 ? url.slice(hashIndex + 1) : '';
|
|
const keptHashParts = rawHash.split('&').filter((part) => {
|
|
if (!part) {
|
|
return false;
|
|
}
|
|
const [rawKey = ''] = part.split('=');
|
|
try {
|
|
return !nextKeys.has(decodeURIComponent(rawKey));
|
|
} catch (_error) {
|
|
return !nextKeys.has(rawKey);
|
|
}
|
|
});
|
|
return `${baseUrl}#${keptHashParts.concat(pairs).join('&')}`;
|
|
}
|
|
|
|
function normalizeTargetPath(value) {
|
|
const trimmed = String(value || '').trim();
|
|
if (!trimmed.startsWith('/')) {
|
|
return '';
|
|
}
|
|
|
|
const normalized = trimmed.replace(/\/+$/u, '') || '/';
|
|
return ALLOWED_TARGET_PATHS.has(normalized) ? normalized : '';
|
|
}
|
|
|
|
function resolveLaunchTargetQuery(query) {
|
|
const targetPath = normalizeTargetPath(query && query.targetPath);
|
|
const work = String((query && query.work) || '').trim();
|
|
if (!targetPath || !work) {
|
|
return {};
|
|
}
|
|
|
|
return {
|
|
targetPath,
|
|
work,
|
|
};
|
|
}
|
|
|
|
function buildWebViewSharePath(query = {}, basePath = WEB_VIEW_SHARE_PATH) {
|
|
const launchTarget = resolveLaunchTargetQuery(query);
|
|
if (!launchTarget.targetPath) {
|
|
return basePath;
|
|
}
|
|
|
|
return appendQuery(basePath, {
|
|
targetPath: launchTarget.targetPath,
|
|
work: launchTarget.work,
|
|
});
|
|
}
|
|
|
|
function buildWebViewShareTimelineQuery(query = {}) {
|
|
const launchTarget = resolveLaunchTargetQuery(query);
|
|
if (!launchTarget.targetPath) {
|
|
return '';
|
|
}
|
|
|
|
return new URLSearchParams({
|
|
targetPath: launchTarget.targetPath,
|
|
work: launchTarget.work,
|
|
}).toString();
|
|
}
|
|
|
|
function normalizeShareTargetMessageData(value) {
|
|
const message = value && value.data ? value.data : value;
|
|
if (!message || message.type !== SHARE_TARGET_MESSAGE_TYPE) {
|
|
return null;
|
|
}
|
|
|
|
const payload = message.payload || {};
|
|
const launchTarget = resolveLaunchTargetQuery(payload);
|
|
if (!launchTarget.targetPath) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
...launchTarget,
|
|
title: String(payload.title || '').trim(),
|
|
};
|
|
}
|
|
|
|
function resolveShareTargetFromWebViewMessage(detail) {
|
|
const dataList = detail && Array.isArray(detail.data) ? detail.data : [];
|
|
for (let index = dataList.length - 1; index >= 0; index -= 1) {
|
|
const target = normalizeShareTargetMessageData(dataList[index]);
|
|
if (target) {
|
|
return target;
|
|
}
|
|
}
|
|
|
|
return normalizeShareTargetMessageData(detail);
|
|
}
|
|
|
|
function appendLaunchTargetToEntryUrl(entryUrl, query) {
|
|
const launchTarget = resolveLaunchTargetQuery(query);
|
|
if (!launchTarget.targetPath) {
|
|
return entryUrl;
|
|
}
|
|
|
|
const rawEntryUrl = String(entryUrl || '').trim();
|
|
const hashIndex = rawEntryUrl.indexOf('#');
|
|
const entryWithoutHash =
|
|
hashIndex >= 0 ? rawEntryUrl.slice(0, hashIndex) : rawEntryUrl;
|
|
const hash = hashIndex >= 0 ? rawEntryUrl.slice(hashIndex) : '';
|
|
const queryIndex = entryWithoutHash.indexOf('?');
|
|
const entryBase =
|
|
queryIndex >= 0 ? entryWithoutHash.slice(0, queryIndex) : entryWithoutHash;
|
|
const entrySearch =
|
|
queryIndex >= 0 ? entryWithoutHash.slice(queryIndex) : '';
|
|
const targetUrl = `${trimTrailingSlash(entryBase)}${launchTarget.targetPath}${entrySearch}${hash}`;
|
|
|
|
return appendQuery(targetUrl, {
|
|
work: launchTarget.work,
|
|
});
|
|
}
|
|
|
|
function resolveWebViewUrlFromRuntimeConfig(
|
|
authResult,
|
|
launchQuery = {},
|
|
runtimeConfig = {},
|
|
) {
|
|
const entryUrl = appendLaunchTargetToEntryUrl(
|
|
String(runtimeConfig.webViewEntryUrl || '').trim(),
|
|
launchQuery,
|
|
);
|
|
const sourcedUrl = appendQuery(entryUrl, runtimeConfig.sourceQuery || {});
|
|
if (!authResult || !authResult.token) {
|
|
return sourcedUrl;
|
|
}
|
|
|
|
return appendHashParams(sourcedUrl, {
|
|
auth_provider: 'wechat',
|
|
auth_token: authResult.token,
|
|
auth_binding_status: authResult.bindingStatus,
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
appendHashParams,
|
|
appendLaunchTargetToEntryUrl,
|
|
appendQuery,
|
|
buildWebViewSharePath,
|
|
buildWebViewShareTimelineQuery,
|
|
normalizeTargetPath,
|
|
resolveShareTargetFromWebViewMessage,
|
|
resolveLaunchTargetQuery,
|
|
resolveWebViewUrlFromRuntimeConfig,
|
|
};
|