Son CV dans un terminal web en Javascript!
https://terminal-cv.gregandev.fr
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
9.8 KiB
324 lines
9.8 KiB
#![deny(clippy::all)]
|
|
|
|
extern crate parcel_sourcemap;
|
|
|
|
use js_sys::Uint8Array;
|
|
use parcel_sourcemap::{Mapping, OriginalLocation, SourceMap as NativeSourceMap};
|
|
use rkyv::AlignedVec;
|
|
use serde::Serialize;
|
|
use std::convert::TryFrom;
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
#[derive(Serialize)]
|
|
#[allow(non_snake_case)]
|
|
struct VLQResult {
|
|
mappings: String,
|
|
sources: Vec<String>,
|
|
sourcesContent: Vec<String>,
|
|
names: Vec<String>,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
struct PositionResult {
|
|
line: u32,
|
|
column: u32,
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
#[derive(Serialize)]
|
|
struct MappingResult {
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
original: Option<PositionResult>,
|
|
generated: PositionResult,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
source: Option<u32>,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
name: Option<u32>,
|
|
}
|
|
|
|
impl From<&Mapping> for MappingResult {
|
|
fn from(mapping: &Mapping) -> MappingResult {
|
|
MappingResult {
|
|
generated: PositionResult {
|
|
line: mapping.generated_line + 1,
|
|
column: mapping.generated_column,
|
|
},
|
|
original: mapping.original.map(|p| PositionResult {
|
|
line: p.original_line + 1,
|
|
column: p.original_column,
|
|
}),
|
|
name: mapping.original.and_then(|p| p.name),
|
|
source: mapping.original.map(|p| p.source),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub struct SourceMap {
|
|
map: NativeSourceMap,
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
#[allow(non_snake_case)]
|
|
impl SourceMap {
|
|
#[wasm_bindgen(constructor)]
|
|
pub fn new(project_root: String, buffer: JsValue) -> Result<SourceMap, JsValue> {
|
|
if !buffer.is_undefined() {
|
|
return Ok(SourceMap {
|
|
map: NativeSourceMap::from_buffer(
|
|
&project_root,
|
|
&Uint8Array::from(buffer).to_vec(),
|
|
)?,
|
|
});
|
|
}
|
|
|
|
Ok(SourceMap {
|
|
map: NativeSourceMap::new(&project_root),
|
|
})
|
|
}
|
|
|
|
pub fn getProjectRoot(&self) -> String {
|
|
self.map.project_root.clone()
|
|
}
|
|
|
|
pub fn addVLQMap(
|
|
&mut self,
|
|
vlq_mappings: String,
|
|
sources: JsValue,
|
|
sources_content: JsValue,
|
|
names: JsValue,
|
|
line_offset: i32,
|
|
column_offset: i32,
|
|
) -> Result<JsValue, JsValue> {
|
|
let sources_string: Vec<String> = sources.into_serde().unwrap();
|
|
let sources_content_string: Vec<String> = sources_content.into_serde().unwrap();
|
|
let names_string: Vec<String> = names.into_serde().unwrap();
|
|
self.map.add_vlq_map(
|
|
vlq_mappings.as_bytes(),
|
|
sources_string.iter().map(|s| s.as_str()).collect(),
|
|
sources_content_string.iter().map(|s| s.as_str()).collect(),
|
|
names_string.iter().map(|s| s.as_str()).collect(),
|
|
line_offset.into(),
|
|
column_offset.into(),
|
|
)?;
|
|
|
|
Ok(JsValue::UNDEFINED)
|
|
}
|
|
|
|
pub fn toVLQ(&mut self) -> Result<JsValue, JsValue> {
|
|
let mut vlq_output: Vec<u8> = vec![];
|
|
self.map.write_vlq(&mut vlq_output)?;
|
|
|
|
let result = VLQResult {
|
|
mappings: String::from_utf8(vlq_output).unwrap(),
|
|
sources: self.map.get_sources().clone(),
|
|
sourcesContent: self.map.get_sources_content().clone(),
|
|
names: self.map.get_names().clone(),
|
|
};
|
|
Ok(JsValue::from_serde(&result).unwrap())
|
|
}
|
|
|
|
pub fn getMappings(&self) -> Result<JsValue, JsValue> {
|
|
let mut mappings: Vec<MappingResult> = vec![];
|
|
for mapping in self.map.get_mappings().iter() {
|
|
mappings.push(MappingResult {
|
|
generated: PositionResult {
|
|
line: (mapping.generated_line + 1) as u32,
|
|
column: mapping.generated_column,
|
|
},
|
|
original: mapping.original.map(|p| PositionResult {
|
|
line: p.original_line + 1,
|
|
column: p.original_column,
|
|
}),
|
|
name: mapping.original.and_then(|p| p.name),
|
|
source: mapping.original.map(|p| p.source),
|
|
});
|
|
}
|
|
Ok(JsValue::from_serde(&mappings).unwrap())
|
|
}
|
|
|
|
pub fn getSources(&self) -> Result<JsValue, JsValue> {
|
|
Ok(JsValue::from_serde(&self.map.get_sources()).unwrap())
|
|
}
|
|
|
|
pub fn getSourcesContent(&self) -> Result<JsValue, JsValue> {
|
|
Ok(JsValue::from_serde(&self.map.get_sources_content()).unwrap())
|
|
}
|
|
|
|
pub fn getNames(&self) -> Result<JsValue, JsValue> {
|
|
Ok(JsValue::from_serde(&self.map.get_names()).unwrap())
|
|
}
|
|
|
|
pub fn addName(&mut self, name: &str) -> u32 {
|
|
self.map.add_name(name)
|
|
}
|
|
|
|
pub fn addSource(&mut self, source: &str) -> u32 {
|
|
self.map.add_source(source)
|
|
}
|
|
|
|
pub fn getName(&self, index: u32) -> String {
|
|
self.map.get_name(index).unwrap_or("").to_string()
|
|
}
|
|
|
|
pub fn getSource(&self, index: u32) -> String {
|
|
self.map.get_source(index).unwrap_or("").to_string()
|
|
}
|
|
|
|
pub fn getNameIndex(&self, name: &str) -> i32 {
|
|
self.map
|
|
.get_name_index(name)
|
|
.map(|v| i32::try_from(v).unwrap())
|
|
.unwrap_or(-1)
|
|
}
|
|
|
|
pub fn getSourceIndex(&self, source: &str) -> Result<JsValue, JsValue> {
|
|
Ok(JsValue::from(
|
|
self.map
|
|
.get_source_index(source)?
|
|
.map(|v| i32::try_from(v).unwrap())
|
|
.unwrap_or(-1),
|
|
))
|
|
}
|
|
|
|
pub fn addIndexedMappings(&mut self, mappings_arr: &[i32]) {
|
|
let mappings_count = mappings_arr.len();
|
|
let mut generated_line: u32 = 0; // 0
|
|
let mut generated_column: u32 = 0; // 1
|
|
let mut original_line: i32 = 0; // 2
|
|
let mut original_column: i32 = 0; // 3
|
|
let mut original_source: i32 = 0; // 4
|
|
for (i, item) in mappings_arr.iter().enumerate().take(mappings_count) {
|
|
let value = *item;
|
|
|
|
match i % 6 {
|
|
0 => {
|
|
generated_line = value as u32;
|
|
}
|
|
1 => {
|
|
generated_column = value as u32;
|
|
}
|
|
2 => {
|
|
original_line = value;
|
|
}
|
|
3 => {
|
|
original_column = value;
|
|
}
|
|
4 => {
|
|
original_source = value;
|
|
}
|
|
5 => {
|
|
self.map.add_mapping(
|
|
generated_line,
|
|
generated_column,
|
|
if original_line > -1 && original_column > -1 && original_source > -1 {
|
|
Some(OriginalLocation {
|
|
original_line: original_line as u32,
|
|
original_column: original_column as u32,
|
|
source: original_source as u32,
|
|
name: if value > -1 { Some(value as u32) } else { None },
|
|
})
|
|
} else {
|
|
None
|
|
},
|
|
);
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn toBuffer(&self) -> Result<JsValue, JsValue> {
|
|
let mut buffer_data = AlignedVec::new();
|
|
self.map.to_buffer(&mut buffer_data)?;
|
|
Ok(Uint8Array::from(buffer_data.as_slice()).into())
|
|
}
|
|
|
|
pub fn addSourceMap(
|
|
&mut self,
|
|
previous_map_instance: &mut SourceMap,
|
|
line_offset: i32,
|
|
) -> Result<JsValue, JsValue> {
|
|
self.map
|
|
.add_sourcemap(&mut previous_map_instance.map, line_offset.into())?;
|
|
|
|
Ok(JsValue::UNDEFINED)
|
|
}
|
|
|
|
pub fn setSourceContentBySource(
|
|
&mut self,
|
|
source: &str,
|
|
source_content: &str,
|
|
) -> Result<JsValue, JsValue> {
|
|
let source_index = self.addSource(source) as usize;
|
|
self.map.set_source_content(source_index, source_content)?;
|
|
|
|
Ok(JsValue::UNDEFINED)
|
|
}
|
|
|
|
pub fn getSourceContentBySource(&self, source: &str) -> Result<JsValue, JsValue> {
|
|
let source_index = self.map.get_source_index(source)?;
|
|
|
|
match source_index {
|
|
Some(i) => {
|
|
let source_content = self.map.get_source_content(i)?;
|
|
Ok(JsValue::from_str(source_content))
|
|
}
|
|
None => Ok(JsValue::from_str("")),
|
|
}
|
|
}
|
|
|
|
pub fn addEmptyMap(
|
|
&mut self,
|
|
source: &str,
|
|
source_content: &str,
|
|
line_offset: i32,
|
|
) -> Result<JsValue, JsValue> {
|
|
self.map
|
|
.add_empty_map(source, source_content, line_offset.into())?;
|
|
|
|
Ok(JsValue::UNDEFINED)
|
|
}
|
|
|
|
pub fn extends(&mut self, previous_map_instance: &mut SourceMap) -> Result<JsValue, JsValue> {
|
|
self.map.extends(&mut previous_map_instance.map)?;
|
|
|
|
Ok(JsValue::UNDEFINED)
|
|
}
|
|
|
|
pub fn findClosestMapping(&mut self, generated_line: u32, generated_column: u32) -> JsValue {
|
|
match self
|
|
.map
|
|
.find_closest_mapping(generated_line, generated_column)
|
|
{
|
|
Some(mapping) => JsValue::from_serde(&MappingResult::from(&mapping)).unwrap(),
|
|
None => JsValue::NULL,
|
|
}
|
|
}
|
|
|
|
pub fn offsetLines(
|
|
&mut self,
|
|
generated_line: u32,
|
|
generated_line_offset: i32,
|
|
) -> Result<JsValue, JsValue> {
|
|
self.map
|
|
.offset_lines(generated_line, generated_line_offset.into())?;
|
|
|
|
Ok(JsValue::UNDEFINED)
|
|
}
|
|
|
|
pub fn offsetColumns(
|
|
&mut self,
|
|
generated_line: u32,
|
|
generated_column: u32,
|
|
generated_column_offset: i32,
|
|
) -> Result<JsValue, JsValue> {
|
|
self.map.offset_columns(
|
|
generated_line,
|
|
generated_column,
|
|
generated_column_offset.into(),
|
|
)?;
|
|
|
|
Ok(JsValue::UNDEFINED)
|
|
}
|
|
}
|
|
|