Added out directory (to start the project without install dependencies)

This commit is contained in:
Hieu C. Nguyen 2021-07-02 21:46:11 +07:00
parent 652bebf1b4
commit c3083df667
8 changed files with 158 additions and 2 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
out
node_modules
.vscode-test/
*.vsix

8
out/config.js Normal file
View File

@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const CSConfig = {
SEARCH_ENDPOINT: `https://www.google.com/search?q=site%3Astackoverflow.com+`,
SEARCH_PHARSE_START: `//find`,
SEARCH_PHARSE_END: `.`
};
exports.default = CSConfig;

47
out/extension.js Normal file
View File

@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.activate = void 0;
const vscode = require("vscode");
const config_1 = require("./config");
const search_1 = require("./utils/search");
function activate(context) {
const disposable = vscode.commands.registerCommand('extension.copilot-clone-settings', () => {
vscode.window.showInformationMessage('Show settings');
});
context.subscriptions.push(disposable);
const provider = {
provideInlineCompletionItems: async (document, position, context, token) => {
const textBeforeCursor = document.getText(new vscode.Range(position.with(undefined, 0), position));
if (textBeforeCursor.indexOf(config_1.default.SEARCH_PHARSE_START) == 0 && textBeforeCursor[textBeforeCursor.length - 1] === config_1.default.SEARCH_PHARSE_END) {
let rs;
try {
rs = await search_1.search(textBeforeCursor);
}
catch (err) {
vscode.window.showErrorMessage(err.toString());
return { items: [] };
}
if (rs == null) {
return { items: [] };
}
const items = new Array();
rs.results.forEach((item, i) => {
const output = `\n// Source: https://stackoverflow.com${item.sourceURL}\n${item.code}`;
items.push({
text: output,
range: new vscode.Range(position.translate(0, output.length), position),
trackingId: `snippet-${i}`,
});
});
return { items };
}
return { items: [] };
},
};
vscode.languages.registerInlineCompletionItemProvider({ pattern: "**" }, provider);
// Be aware that the API around `getInlineCompletionItemController` will not be finalized as is!
vscode.window.getInlineCompletionItemController(provider).onDidShowCompletionItem(e => {
const id = e.completionItem.trackingId;
});
}
exports.activate = activate;

View File

@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractGoogleResults = void 0;
const config_1 = require("../config");
const fetchPageContent_1 = require("./fetchPageContent");
// Get search results from google, then return a list of stackoverflow links
function extractGoogleResults(keyword) {
return new Promise((resolve, reject) => {
return fetchPageContent_1.fetchPageTextContent(`${config_1.default.SEARCH_ENDPOINT}${keyword.replace(/\s/, '+')}`)
.then(rs => {
let urls = rs.textContent.match(/(https:\/\/stackoverflow.com\/[a-z0-9-/]+)/g);
urls && (urls = urls.filter((url, i, list) => list.indexOf(url) === i));
resolve(urls);
})
.catch(reject);
});
}
exports.extractGoogleResults = extractGoogleResults;

View File

@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractSnippetResults = void 0;
const jsdom_1 = require("jsdom");
// Extract and sort stackoverflow answers
function extractSnippetResults(options) {
var doc = new jsdom_1.JSDOM(options.textContent);
let answersWithCodeBlock = Array.from(doc.window.document.querySelectorAll(".answer"))
.filter((item) => item.querySelector("code") != null);
let results = answersWithCodeBlock
.map((item) => ({
textContent: item.textContent,
votes: parseInt(item.querySelector(".js-vote-count").textContent),
// TODO: Handle answers with more than one code block
// p/s: they often about explaining the something
code: item.querySelector("code").textContent,
sourceURL: item.querySelector(".js-share-link").href,
hasCheckMark: item.querySelector("iconCheckmarkLg") != null
}))
.filter(item => isCodeValid(item.code));
results.sort(sortSnippetResultFn);
return { url: options.url, results };
}
exports.extractSnippetResults = extractSnippetResults;
function sortSnippetResultFn(a, b) {
if (a.hasCheckMark != b.hasCheckMark) {
return a.hasCheckMark ? 1 : -1;
}
let result = b.votes - a.votes;
return result === 0 ? b.code.length - a.code.length : result;
}
// Check whether the input should be considered as code input or random text
function isCodeValid(input) {
// This is just a temporary solution,
// it would filter codes that are too short
return input.length > 12;
}

View File

@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchPageTextContent = void 0;
const node_fetch_1 = require("node-fetch");
function fetchPageTextContent(url) {
return new Promise((resolve, reject) => {
return node_fetch_1.default(url)
.then(rs => rs.text())
.then(textContent => resolve({ textContent, url }))
.catch(reject);
});
}
exports.fetchPageTextContent = fetchPageTextContent;

33
out/utils/search.js Normal file
View File

@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.search = void 0;
const extractGoogleResults_1 = require("./extractGoogleResults");
const extractStackOverflowResults_1 = require("./extractStackOverflowResults");
const fetchPageContent_1 = require("./fetchPageContent");
// Send search query to google, get answers from stackoverflow
// then extract and return code results
async function search(keyword) {
return new Promise((resolve, reject) => {
extractGoogleResults_1.extractGoogleResults(keyword)
.then(async (urls) => {
if (urls === null) {
return Promise.resolve(null);
}
let results = [];
try {
let fetchResult;
for (const i in urls.splice(0, 6)) {
if (urls[i]) {
fetchResult = await fetchPageContent_1.fetchPageTextContent(urls[i]);
results = results.concat(extractStackOverflowResults_1.extractSnippetResults(fetchResult).results);
}
}
resolve({ results });
}
catch (err) {
reject(err);
}
}).catch(reject);
});
}
exports.search = search;

View File

@ -4,7 +4,7 @@
"target": "es2019",
"lib": ["ES2019"],
"outDir": "out",
"sourceMap": true,
"sourceMap": false,
"strict": true,
"rootDir": "src",
"skipDefaultLibCheck": true,