mirror of https://github.com/sveltejs/svelte
parent
7284997aec
commit
b9d9742d74
@ -1,72 +1,75 @@
|
||||
import { MappedCode } from '../utils/mapped_code';
|
||||
import { Source } from './types';
|
||||
|
||||
interface Replacement {
|
||||
offset: number;
|
||||
length: number;
|
||||
replacement: MappedCode;
|
||||
/**
|
||||
* @param {string} code_slice
|
||||
* @param {number} offset
|
||||
* @param {Source}
|
||||
* @returns {Source}
|
||||
*/
|
||||
export function slice_source(code_slice, offset, { file_basename, filename, get_location }) {
|
||||
return {
|
||||
source: code_slice,
|
||||
get_location: (index) => get_location(index + offset),
|
||||
file_basename,
|
||||
filename
|
||||
};
|
||||
}
|
||||
|
||||
export function slice_source(
|
||||
code_slice: string,
|
||||
offset: number,
|
||||
{ file_basename, filename, get_location }: Source
|
||||
): Source {
|
||||
return {
|
||||
source: code_slice,
|
||||
get_location: (index: number) => get_location(index + offset),
|
||||
file_basename,
|
||||
filename
|
||||
};
|
||||
}
|
||||
|
||||
function calculate_replacements(
|
||||
re: RegExp,
|
||||
get_replacement: (...match: any[]) => Promise<MappedCode>,
|
||||
source: string
|
||||
) {
|
||||
const replacements: Array<Promise<Replacement>> = [];
|
||||
|
||||
source.replace(re, (...match) => {
|
||||
replacements.push(
|
||||
get_replacement(...match).then((replacement) => {
|
||||
const matched_string = match[0];
|
||||
const offset = match[match.length - 2];
|
||||
|
||||
return { offset, length: matched_string.length, replacement };
|
||||
})
|
||||
);
|
||||
return '';
|
||||
});
|
||||
/**
|
||||
* @param {RegExp} re
|
||||
* @param {(...match: any[]) => Promise<MappedCode>} get_replacement
|
||||
* @param {string} source
|
||||
*/
|
||||
function calculate_replacements(re, get_replacement, source) {
|
||||
|
||||
return Promise.all(replacements);
|
||||
/**
|
||||
* @type {Array<Promise<Replacement>>}
|
||||
*/
|
||||
const replacements = [];
|
||||
source.replace(re, (...match) => {
|
||||
replacements.push(get_replacement(...match).then((replacement) => {
|
||||
const matched_string = match[0];
|
||||
const offset = match[match.length - 2];
|
||||
return { offset, length: matched_string.length, replacement };
|
||||
}));
|
||||
return '';
|
||||
});
|
||||
return Promise.all(replacements);
|
||||
}
|
||||
|
||||
function perform_replacements(replacements: Replacement[], source: Source): MappedCode {
|
||||
const out = new MappedCode();
|
||||
let last_end = 0;
|
||||
/**
|
||||
* @param {Replacement[]} replacements
|
||||
* @param {Source} source
|
||||
* @returns {MappedCode}
|
||||
*/
|
||||
function perform_replacements(replacements, source) {
|
||||
const out = new MappedCode();
|
||||
let last_end = 0;
|
||||
for (const { offset, length, replacement } of replacements) {
|
||||
const unchanged_prefix = MappedCode.from_source(slice_source(source.source.slice(last_end, offset), last_end, source));
|
||||
out.concat(unchanged_prefix).concat(replacement);
|
||||
last_end = offset + length;
|
||||
}
|
||||
const unchanged_suffix = MappedCode.from_source(slice_source(source.source.slice(last_end), last_end, source));
|
||||
return out.concat(unchanged_suffix);
|
||||
}
|
||||
|
||||
for (const { offset, length, replacement } of replacements) {
|
||||
const unchanged_prefix = MappedCode.from_source(
|
||||
slice_source(source.source.slice(last_end, offset), last_end, source)
|
||||
);
|
||||
out.concat(unchanged_prefix).concat(replacement);
|
||||
last_end = offset + length;
|
||||
}
|
||||
/**
|
||||
* @param {RegExp} regex
|
||||
* @param {(...match: any[]) => Promise<MappedCode>} get_replacement
|
||||
* @param {Source} location
|
||||
* @returns {Promise<MappedCode>}
|
||||
*/
|
||||
export async function replace_in_code(regex, get_replacement, location) {
|
||||
const replacements = await calculate_replacements(regex, get_replacement, location.source);
|
||||
return perform_replacements(replacements, location);
|
||||
}
|
||||
|
||||
const unchanged_suffix = MappedCode.from_source(
|
||||
slice_source(source.source.slice(last_end), last_end, source)
|
||||
);
|
||||
|
||||
return out.concat(unchanged_suffix);
|
||||
}
|
||||
|
||||
export async function replace_in_code(
|
||||
regex: RegExp,
|
||||
get_replacement: (...match: any[]) => Promise<MappedCode>,
|
||||
location: Source
|
||||
): Promise<MappedCode> {
|
||||
const replacements = await calculate_replacements(regex, get_replacement, location.source);
|
||||
|
||||
return perform_replacements(replacements, location);
|
||||
}
|
||||
/** @typedef {Object} Replacement
|
||||
* @property {number} offset
|
||||
* @property {number} length
|
||||
* @property {MappedCode} replacement
|
||||
*/
|
||||
Loading…
Reference in new issue