vscode extension completion: how to replace the original text? - vscode-extensions

const scarlingProvider = vscode.languages.registerCompletionItemProvider(
'javascript',
{
provideCompletionItems(document, position, token, context) {
const linePrefix = document.lineAt(position).text.substr(0, position.character);
if (!hasChinese(linePrefix)) {
return undefined;
}
const reminds = starling.match(linePrefix)
console.log('reminds: ', reminds);
return [reminds].map(val => {
try {
const item = new vscode.CompletionItem(val, vscode.CompletionItemKind.Method)
item.insertText = `$t('${val}', '${linePrefix.trim()}')`
return item
} catch(err) {
console.log('err: ', err);
}
})
}
},
' '
As above, it's a snippet of a completion extension. I want the selected text to replace the original text instead of inserting that after the original text. What should I do?

You have to specify a range with your completion item. The model can give you the position of the original text for which the provider has been invoked:
const scarlingProvider = vscode.languages.registerCompletionItemProvider(
'javascript',
{
provideCompletionItems(document, position, token, context) {
const linePrefix = document.lineAt(position).text.substr(0, position.character);
if (!hasChinese(linePrefix)) {
return undefined;
}
const info = model.getWordUntilPosition(position);
const range = {
startLineNumber: position.lineNumber,
startColumn: info.startColumn - 1,
endLineNumber: position.lineNumber,
endColumn: info.endColumn,
};
const reminds = starling.match(linePrefix)
console.log('reminds: ', reminds);
return [reminds].map(val => {
try {
return {
label: "<a label>",
kind: CompletionItemKind.Method,
range,
insertText: `$t('${val}', '${linePrefix.trim()}')`,
detail: "<a description>",
}
} catch(err) {
console.log('err: ', err);
}
})
}
},
' '

Related

How to sanitize inputs in nodejs to prevent sql injection?

i have this sanitize function
sanitizeXSS: string => {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
"/": '/',
};
const reg = /[&<>"'/]/ig;
return string.replace(reg, (match)=>(map[match]));
}
And this sanitize function is being used here
addOrUpdateAddress : function (request, resolve)
{
const customerKey = sanitizeXSS(decrypt_key(request.customer_key));
const lat = sanitizeXSS(decrypt_key(request.lat));
const lng = sanitizeXSS(decrypt_key(request.lng));
const line1 = sanitizeXSS(decrypt_key(request.line1));
const line2 = sanitizeXSS(decrypt_key(request.line2));
const city = sanitizeXSS(decrypt_key(request.city));
const pincode = sanitizeXSS(decrypt_key(request.pincode));
const state = sanitizeXSS(decrypt_key(request.state));
const contact = sanitizeXSS(decrypt_key(request.contact));
const landmark = request.landmark?sanitizeXSS(decrypt_key(request.landmark)):null;
let req=request;
if(req.name && req.email)
{
updateUser(req,function(err,result)
{
console.log(err);
console.log(result);
});
}
let addressId = (!req.address_id || req.address_id == null || req.address_id == '')
? -1 : req.address_id;
console.log(addressId);
async.auto({
serviceability : function (cb)
{
searchServiceArea(req,function(err,result)
{
if(err)
{
resolve(null, {'errorMessage':'Address selected not serviceble'}, 203, 'error');
}
else
{
if(!result.hub_id)
{
resolve(null, {'errorMessage':'Address selected not serviceble'}, 203, 'error');
}
if(addressId == -1)
{
let s=mysql.write('customer_address').insert({customer_key: customerKey,line1:line1,line2:line2,lat: lat,lng: lng,city: city,state: state,pincode: pincode,contact: contact,landmark : landmark,updated_at:moment().format("YYYY-MM-DD HH:mm:ss"),created_at:moment().format("YYYY-MM-DD HH:mm:ss")}).then(function(res)
{
if(res.length > 0)
{
cb(null,{address_id:res[0],customer_key: customerKey,line1:line1,line2:line2,lat: lat,lng: lng,city: city,state: state,pincode: pincode,contact: contact,landmark : landmark,updated_at:moment().format("YYYY-MM-DD HH:mm:ss"),created_at:moment().format("YYYY-MM-DD HH:mm:ss"),'hub_id':result.hub_id})
}
else
{
cb(true,{'errorMessage':'Unable to add address try again'})
}
});
}
else
{
let s=mysql.write('customer_address').update({line1:line1,line2:line2,lat: lat,lng: lng,city: city,state: state,pincode: pincode,contact: contact,landmark : landmark,updated_at:moment().format("YYYY-MM-DD HH:mm:ss")}).where({customer_key:customerKey, address_id:addressId}).then(function(res)
{
console.log(res)
if(res == 1)
{
cb(null,{address_id:addressId,customer_key: customerKey,line1:line1,line2:line2,lat: lat,lng: lng,city: city,state: state,pincode: pincode,contact: contact,landmark : landmark,updated_at:moment().format("YYYY-MM-DD HH:mm:ss"),created_at:moment().format("YYYY-MM-DD HH:mm:ss"),'hub_id':result.hub_id})
}
else
{
cb(true,{'errorMessage':'Unable to update address try again'})
}
},
},
);
}
So while inserting the address I'm identifying sql injection. I checked everywhere the possible solutions i was not able to solve it. Please do check the sql query also which i have mentioned.
How to solve this?
That would be a lot of help. Thanks in advance
I'd just use a standard library that already provides sanitization, like node-mysql.
https://github.com/mysqljs/mysql#escaping-query-values
const mysql = require('mysql');
const connection = mysql.createConnection({
host : 'example.org',
user : 'bob',
password : 'secret'
});
const post = {title: 'Hello MySQL', 'content': '...'};
connection.query(
'insert into posts (title, content, updated_at, created_at) values (?, ?, ?, ?);',
[
connection.escape(post.title),
connection.escape(post.content),
connection.escape(new Date()),
connection.escape(new Date())
]
).then((err, res, fields) => {
//do stuff
})

How to change the width of NormalPeoplePicker dropdown

I'm using default example of NormalPeoplePicker from https://developer.microsoft.com/en-us/fluentui#/controls/web/peoplepicker#IPeoplePickerProps.
When the dropdown displays it cuts off longer items (example: 'Anny Lundqvist, Junior Manager of Soft..'). How do I make it wider, so that the full item's text displays?
import * as React from 'react';
import { Checkbox } from 'office-ui-fabric-react/lib/Checkbox';
import { IPersonaProps } from 'office-ui-fabric-react/lib/Persona';
import { IBasePickerSuggestionsProps, NormalPeoplePicker, ValidationState } from 'office-ui-fabric-react/lib/Pickers';
import { people, mru } from '#uifabric/example-data';
const suggestionProps: IBasePickerSuggestionsProps = {
suggestionsHeaderText: 'Suggested People',
mostRecentlyUsedHeaderText: 'Suggested Contacts',
noResultsFoundText: 'No results found',
loadingText: 'Loading',
showRemoveButtons: true,
suggestionsAvailableAlertText: 'People Picker Suggestions available',
suggestionsContainerAriaLabel: 'Suggested contacts',
};
const checkboxStyles = {
root: {
marginTop: 10,
},
};
export const PeoplePickerNormalExample: React.FunctionComponent = () => {
const [delayResults, setDelayResults] = React.useState(false);
const [isPickerDisabled, setIsPickerDisabled] = React.useState(false);
const [mostRecentlyUsed, setMostRecentlyUsed] = React.useState<IPersonaProps[]>(mru);
const [peopleList, setPeopleList] = React.useState<IPersonaProps[]>(people);
const picker = React.useRef(null);
const onFilterChanged = (
filterText: string,
currentPersonas: IPersonaProps[],
limitResults?: number,
): IPersonaProps[] | Promise<IPersonaProps[]> => {
if (filterText) {
let filteredPersonas: IPersonaProps[] = filterPersonasByText(filterText);
filteredPersonas = removeDuplicates(filteredPersonas, currentPersonas);
filteredPersonas = limitResults ? filteredPersonas.slice(0, limitResults) : filteredPersonas;
return filterPromise(filteredPersonas);
} else {
return [];
}
};
const filterPersonasByText = (filterText: string): IPersonaProps[] => {
return peopleList.filter(item => doesTextStartWith(item.text as string, filterText));
};
const filterPromise = (personasToReturn: IPersonaProps[]): IPersonaProps[] | Promise<IPersonaProps[]> => {
if (delayResults) {
return convertResultsToPromise(personasToReturn);
} else {
return personasToReturn;
}
};
const returnMostRecentlyUsed = (currentPersonas: IPersonaProps[]): IPersonaProps[] | Promise<IPersonaProps[]> => {
return filterPromise(removeDuplicates(mostRecentlyUsed, currentPersonas));
};
const onRemoveSuggestion = (item: IPersonaProps): void => {
const indexPeopleList: number = peopleList.indexOf(item);
const indexMostRecentlyUsed: number = mostRecentlyUsed.indexOf(item);
if (indexPeopleList >= 0) {
const newPeople: IPersonaProps[] = peopleList
.slice(0, indexPeopleList)
.concat(peopleList.slice(indexPeopleList + 1));
setPeopleList(newPeople);
}
if (indexMostRecentlyUsed >= 0) {
const newSuggestedPeople: IPersonaProps[] = mostRecentlyUsed
.slice(0, indexMostRecentlyUsed)
.concat(mostRecentlyUsed.slice(indexMostRecentlyUsed + 1));
setMostRecentlyUsed(newSuggestedPeople);
}
};
const onDisabledButtonClick = (): void => {
setIsPickerDisabled(!isPickerDisabled);
};
const onToggleDelayResultsChange = (): void => {
setDelayResults(!delayResults);
};
return (
<div>
<NormalPeoplePicker
// eslint-disable-next-line react/jsx-no-bind
onResolveSuggestions={onFilterChanged}
// eslint-disable-next-line react/jsx-no-bind
onEmptyInputFocus={returnMostRecentlyUsed}
getTextFromItem={getTextFromItem}
pickerSuggestionsProps={suggestionProps}
className={'ms-PeoplePicker'}
key={'normal'}
// eslint-disable-next-line react/jsx-no-bind
onRemoveSuggestion={onRemoveSuggestion}
onValidateInput={validateInput}
removeButtonAriaLabel={'Remove'}
inputProps={{
onBlur: (ev: React.FocusEvent<HTMLInputElement>) => console.log('onBlur called'),
onFocus: (ev: React.FocusEvent<HTMLInputElement>) => console.log('onFocus called'),
'aria-label': 'People Picker',
}}
componentRef={picker}
onInputChange={onInputChange}
resolveDelay={300}
disabled={isPickerDisabled}
/>
<Checkbox
label="Disable People Picker"
checked={isPickerDisabled}
// eslint-disable-next-line react/jsx-no-bind
onChange={onDisabledButtonClick}
styles={checkboxStyles}
/>
<Checkbox
label="Delay Suggestion Results"
defaultChecked={delayResults}
// eslint-disable-next-line react/jsx-no-bind
onChange={onToggleDelayResultsChange}
styles={checkboxStyles}
/>
</div>
);
};
function doesTextStartWith(text: string, filterText: string): boolean {
return text.toLowerCase().indexOf(filterText.toLowerCase()) === 0;
}
function removeDuplicates(personas: IPersonaProps[], possibleDupes: IPersonaProps[]) {
return personas.filter(persona => !listContainsPersona(persona, possibleDupes));
}
function listContainsPersona(persona: IPersonaProps, personas: IPersonaProps[]) {
if (!personas || !personas.length || personas.length === 0) {
return false;
}
return personas.filter(item => item.text === persona.text).length > 0;
}
function convertResultsToPromise(results: IPersonaProps[]): Promise<IPersonaProps[]> {
return new Promise<IPersonaProps[]>((resolve, reject) => setTimeout(() => resolve(results), 2000));
}
function getTextFromItem(persona: IPersonaProps): string {
return persona.text as string;
}
function validateInput(input: string): ValidationState {
if (input.indexOf('#') !== -1) {
return ValidationState.valid;
} else if (input.length > 1) {
return ValidationState.warning;
} else {
return ValidationState.invalid;
}
}
/**
* Takes in the picker input and modifies it in whichever way
* the caller wants, i.e. parsing entries copied from Outlook (sample
* input: "Aaron Reid <aaron>").
*
* #param input The text entered into the picker.
*/
function onInputChange(input: string): string {
const outlookRegEx = /<.*>/g;
const emailAddress = outlookRegEx.exec(input);
if (emailAddress && emailAddress[0]) {
return emailAddress[0].substring(1, emailAddress[0].length - 1);
}
return input;
}
Component which renders suggestion list have fixed width of 180px. Take a look at PeoplePickerItemSuggestion.styles.ts.
What you can do is to modify this class .ms-PeoplePicker-Persona:
.ms-PeoplePicker-Persona {
width: 260px; // Or what ever you want
}
UPDATE - Solution from comments
Change width trough styles property of PeoplePickerItemSuggestion Component
const onRenderSuggestionsItem = (personaProps, suggestionsProps) => (
<PeoplePickerItemSuggestion
personaProps={personaProps}
suggestionsProps={suggestionsProps}
styles={{ personaWrapper: { width: '100%' }}}
/>
);
<NormalPeoplePicker
onRenderSuggestionsItem={onRenderSuggestionsItem}
pickerCalloutProps={{ calloutWidth: 500 }}
...restProps
/>
Working Codepen example
For more information how to customize components read Component Styling.

vuejs this is undefined in my eventListner

I've tried to make a google map in vuejs where the value of the center of my map is shown in my view.
For this, I created my marker and tried to update the value with this.marker = map.center.lng(); or this.setMarkerLng(map.center.lng()); inside an event listner of my method Initmap but none of them work. I got the message:
this is undefined
Outside the eventlistener, everything works.
Can you help?
export default {
mounted: function () {
this.initMap();
},
data() {
return {
marker: {
lng : 'latitude',
lat: 'longitude'
}
}
},
methods: {
///google map init
initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 48.587536, lng: 7.751440},
zoom: 13
});
this.setMarkerLat(map.center.lat());
this.setMarkerLng(map.center.lng());
///Listner
autocomplete.addListener('place_changed', function () {
///call method bug
this.setMarkerLat(map.center.lat());
this.setMarkerLng(map.center.lng());
infowindow.close();
this.marker.lat = map.center.lat();
this.marker.lng = map.center.lng();
marker.setVisible(false);
var place = autocomplete.getPlace();
if (!place.geometry) {
window.alert("No details available for input: '" + place.name + "'");
return;
}
// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17); // Why 17? Because it looks good.
}
marker.setPosition(place.geometry.location);
marker.setVisible(true);
var address = '';
if (place.address_components) {
address = [
(place.address_components[0] && place.address_components[0].short_name || ''),
(place.address_components[1] && place.address_components[1].short_name || ''),
(place.address_components[2] && place.address_components[2].short_name || '')
].join(' ');
}
},
setMarkerLng: function(lng) {
this.marker.lng = lng;
},
setMarkerLat: function(lat){
this.marker.lat = lat;
}
}
}
Try to use the arrow function ()=> in order to be able to access this scope like :
autocomplete.addListener('place_changed', ()=> {
...
}

How to write unit test component with FileReader.addEventListener in angular 8?

I use angular 8 and i want to test my component with FileReader.
I can not test a FileReader in my processFile function.
Maybe my work is badly written? Can you help me please to understand.
IF I understand correctly, I have to test a class (Filereader) in a process function
my component
processFile(imageInput: any) {
const file: File = imageInput.files[0];
const reader = new FileReader();
let size: number = 2097152
if (file) {
if (file.size <= size) {
this.sharingDataService.setUploadIsOk(true)
reader.addEventListener('progress', (event:any) =>{
this.progressValue = this.progressBar(event)
if (event.lengthComputable) {
// console.log(event.loaded+ " / " + event.total)
}
})
reader.addEventListener('loadstart', (event:any) =>{
this.progressValue =0;
this.textDuringUploadBefore = "No"
this.textDuringUploadAfter = ''
// console.log('start');
})
reader.addEventListener('loadend', (event:any) =>{
// console.log('end');
})
reader.addEventListener('load', (event: any) => {
console.log(event);
this.selectedFile = new ImageSnippet(event.target.result, file);
this.fileName = this.selectedFile.file.name;
this.fileNameExt =this.fileName.split('.').pop();
this.displayAddPhoto = false;
this.selectedFile.status = 'ok';
this.getLoadCallBack(file)
// this.ng2ImgMax.resizeImage(file, 900,600).subscribe(
// result =>{
// // console.log('compress', );
// this.textDuringUploadAfter= "Yes!!!"
// this.textDuringUploadBefore= ''
// this.fileForm.patchValue({
// image: new File([result], result.name)
// });
// this.imageIsLoad = true
// this.sharingDataService.setUploadIsOk(false)
// }
// )
// this.imageOutput.emit(this.fileForm)
});
reader.readAsDataURL(file);
} else {
const msg ="This picture is too big."
+ '<br/>' + "Please upload an image of less than 2MB."
// this.sharedFunctionService.openDialogAlert(msg, 'home')
this.errorService.openDialogError(msg)
this.imageIsLoad = false
this.sharingDataService.setUploadIsOk(false)
}
}
}
getLoadCallBack(file:File){
this.ng2ImgMax.resizeImage(file, 900,600).subscribe(
result =>{
// console.log('compress', );
this.textDuringUploadAfter= "Yes"
this.textDuringUploadBefore= ''
this.fileForm.patchValue({
image: new File([result], result.name)
});
console.log(this.fileForm);
this.imageIsLoad = true
this.sharingDataService.setUploadIsOk(false)
}
)
this.imageOutput.emit(this.fileForm)
}
my spec.ts
it('processFile', () => {
// const mockEvt = { target: { files: [fileInput] } };
// const mockReader: FileReader = jasmine.createSpyObj('FileReader', ['readAsDataURL', 'onload']);
// spyOn(window as any, 'FileReader').and.returnValue(mockReader);
// spyOn(component, 'getLoadCallBack').and.callThrough();
const file = new File([''], 'test-file.jpg', { lastModified: null, type: 'image/jpeg' });
const fileInput = { files: [file] };
const eventListener = jasmine.createSpy();
spyOn(window as any, "FileReader").and.returnValue({
addEventListener: eventListener
})
component.processFile(fileInput);
i have got an error
TypeError: reader.readAsDataURL is not a function
how to test my processFile function?
I trie many way but no sucess

I am getting this error ,"value for message cannot be cast from double to string"

I am getting this error when I am trying pass object to axios method "value for message cannot be cast from double to string". Does any one have Idea about this.
I have added my two functions.
addNotes = (formData) => {
let noteText = ''
Object.keys(formData).map((item) => {
noteText += formData[item] !== undefined ? `${formData[item]} \n` : ``
})
let localLocation = `${this.state.localAddress.locality}, ${this.state.localAddress.subLocality}`
let { userMetaData, graphListlimit, graphListoffset, imdCode } = this.state
let obj = {
'edEmployeeCode': userMetaData.ed_employee_code,
'edName': userMetaData.ed_name,
'edRoleCode': userMetaData.ed_role_code,
'imdCode': imdCode,
'imdSegment': null,
'bnNoteText': noteText,
'location': localLocation,
'meetingType': this.state.meetingType
}
this.props.onAddNotesAction(obj)
}
export const addNotesAction = (obj) => {
let params = {
ed_employee_code: obj.empCode,
ed_role_code: obj.empRoleCode,
ed_channel: obj.empChannel,
ed_name: obj.edName,
imd_code: obj.imdCode,
imd_segment: null,
bn_note_text: obj.bnNoteText,
location: obj.location,
meeting_type: obj.meetingType
}
return dispatch => {
axios.defaults.headers.common['Authorization'] = obj.token;
axios.post(`${Config.apiRootPath}/meetings/addbranchnote`,
params,
).then(response => {
dispatch(addNotesSuccess(response));
}).catch(err => {
dispatch(addNotesFailure(err.response));
});
};
};