Created
August 8, 2021 14:23
-
-
Save Geczy/98b423867b865c2b36a73a32a0f757f0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const vscode = require('vscode'); | |
const path = require('path'); | |
const fetch = require("node-fetch"); | |
const jsdom = require('jsdom') | |
const getmac = require('getmac') | |
let global_questions = []; | |
let global_question_index = 0; | |
let global_last_response = null; | |
let global_current_language = "" | |
let panel = null; | |
async function google_analytics(event_name){ | |
try{ | |
const params = { | |
v: 1, | |
t: 'event', | |
tid: 'UA-19034238-5', | |
cid: callMac(), | |
ec: 'general', | |
el: global_current_language, | |
ea: event_name | |
}; | |
let url = 'https://www.google-analytics.com/collect' + '?' + ( new URLSearchParams( params ) ).toString(); | |
const rawResponse = fetch(url); | |
}catch(err){ | |
} | |
} | |
async function get_json_stackoverflow(base_url, params){ | |
base_url += '?' + ( new URLSearchParams( params ) ).toString(); | |
const res = await fetch(base_url) | |
const json = await res.json() | |
return json | |
} | |
function string_replacements_stack(post){ | |
return post.replaceAll("<code>", "") | |
.replaceAll("</code>", "") | |
.replaceAll(">", ">") | |
.replaceAll("<", "<") | |
.replaceAll(">>> ", "") | |
.replaceAll(">>>", "") | |
} | |
function process_code_stack(post){ | |
return post.replaceAll("<pre><code>", '<button class="btn btn-send-to-editor">SEND TO EDITOR</button><br><pre><code>') | |
} | |
async function set_global_stack_questions_response(title){ | |
const params = { | |
order: 'desc', | |
sort: 'relevance', | |
title: title, | |
site: 'stackoverflow', | |
tagged: global_current_language, | |
filter: '!6VvPDzQ)wlg1u', | |
key: 'x50f*DV4VX2ZzPIuvA)BmQ((' | |
}; | |
let url = 'https://api.stackexchange.com/2.3/similar' | |
global_last_response = await get_json_stackoverflow(url, params) | |
global_questions = []; | |
global_question_index = 0; | |
try{ | |
for(var question_i in global_last_response['items']){ | |
let question = global_last_response['items'][question_i] | |
if(question['is_answered']){ | |
global_questions.push(question) | |
} | |
} | |
}catch(err){} | |
} | |
async function build_html_body(logoSrc){ | |
let html = '<div style="text-align:center"> <img style="margin-top:10px; margin-bottom:10px; width:200px;" src="'+logoSrc+'">' | |
try{ | |
if (global_last_response['quota_remaining'] < 5000){ | |
html += '<h3>Searches left: ' + global_last_response['quota_remaining'].toString() + ' / ' + global_last_response['quota_max'].toString() + '</h3>' | |
} | |
html += '<h4>Like this extension? Please consider <a href="https://www.buymeacoffee.com/markfobert">buying me a coffee.</a></h4>' | |
html += '<h6 style="color:gray">Content sourced from the <a style="color:gray" href="https://stackexchange.com/">Stack Exchange Network</a></a></h6></div><hr>' | |
}catch(err){} | |
if (global_questions.length == 0) { | |
html += '<div style="text-align:center">' | |
html += '<h3>No Results Found</h3>'; | |
html += '<h4>Try refining your search</h4>'; | |
html += '</div>' | |
return html; | |
} | |
let question = global_questions[global_question_index] | |
let date = new Date(parseInt(question['creation_date']) * 1000) | |
html += '<div style="position:relative;text-align:center">' | |
html += '<h3 style="display:inline-block;margin-bottom:5px"><a style="color:white" href="' + question['link'] + '">' + question['title'] + "</a></h3>" | |
html += '<h5 >Asked by <a style="color:white" href="' + question['owner']['link'] + '">' + question['owner']['display_name'] + "</a> on " + date.toDateString() + " </h5>" | |
if(global_question_index > 0){ | |
html += '<button class="btn btn-previous-page" style="display:inline-block;margin-right:10px;font-size:1.5rem"> << </button>' | |
}else{ | |
html += '<button class="btn btn-previous-page" style="display:inline-block;margin-right:10px;font-size:1.5rem;visibility:hidden"> << </button>' | |
} | |
if(global_questions.length > 1){ | |
html += '<button class="btn btn-show-results" style="display:inline-block;margin-right:5px;margin-left:5px;font-size:1.5rem"> = </button>' | |
} | |
html += '<div id="title_popup" style="display:none;position:absolute;padding:20px;margin-left:auto;margin-right:auto;background:rgba(0, 0, 0, 0.9); border-radius: 10px; width: 80%;left:10%;right:10%;z-index:100;">' | |
for(var question_i in global_questions){ | |
let tmp_question = global_questions[question_i] | |
html += '<h4><a id="' + question_i.toString() + '" class="question" href="#">' + tmp_question['title'] + '</a></h4>' | |
} | |
html += '</div>' | |
if(global_question_index < global_questions.length - 1){ | |
html += '<button class="btn btn-next-page" style="display:inline-block;margin-left:10px;font-size:1.5rem"> >> </button>' | |
}else{ | |
html += '<button class="btn btn-next-page" style="display:inline-block;margin-left:10px;font-size:1.5rem;visibility:hidden"> >> </button>' | |
} | |
html += '</div>' | |
html += process_code_stack(question['body'].toString()) + "<br><hr>" | |
for(var answer_i in question['answers']){ | |
let answer = question['answers'][answer_i] | |
date = new Date(parseInt(answer['creation_date']) * 1000) | |
html += '<div style="text-align:center"><h5>Answered by <a style="color:white" href="' + answer['owner']['link'] + '">' + answer['owner']['display_name'] + "</a> on " + date.toDateString() + " </h5></div>" | |
html += process_code_stack(answer['body'].toString()) + "<br><hr>" | |
} | |
const {JSDOM} = jsdom; | |
const dom = new JSDOM(html.toString()); | |
const $ = (require('jquery'))(dom.window); | |
const code_blocks = ($('pre')) | |
for (let i = 0; i < code_blocks.length; i++) { | |
const code_block = code_blocks[i] | |
$(code_block).clone().css('display', 'none').attr('class','nohighlight').insertBefore( $(code_block) ) | |
} | |
html = $('body').html() | |
return html.toString(); | |
} | |
function create_panel(){ | |
panel = vscode.window.createWebviewPanel( | |
'stackFinder', | |
'StackFinder', | |
vscode.ViewColumn.Two, | |
{ | |
enableScripts: true | |
} | |
); | |
} | |
//authorization https://stackoverflow.com/oauth/dialog?client_id=20721&scope=no_expiry&redirect_uri=https://stackoverflow.com/oauth/login_success | |
const callMac = () =>{ | |
return getmac.default().toString() | |
} | |
/** | |
* @param {vscode.ExtensionContext} context | |
*/ | |
async function activate(context) { | |
let disposable = vscode.commands.registerCommand('stackfinder.search', async function () { | |
let activeEditor = vscode.window.activeTextEditor; | |
if (!activeEditor) { return; } | |
global_current_language = activeEditor.document.languageId | |
align_languages() | |
google_analytics('search') | |
//edit text in console | |
let line_start = activeEditor.document.lineAt(activeEditor.selection.active.line); | |
const line_number_start = line_start.lineNumber; | |
const selection_current_line = new vscode.Selection(line_number_start, line_start.range.start.character, | |
line_number_start, line_start.range.end.character) | |
activeEditor.selection = selection_current_line; | |
const current_line_text = activeEditor.document.getText(selection_current_line); | |
//const stack_questions = await get_stack_answers(current_line_text); | |
activeEditor.edit(editBuilder => { | |
editBuilder.replace(selection_current_line, ""); | |
}); | |
if(panel == null){ | |
create_panel() | |
} | |
if(panel._store._isDisposed){ | |
create_panel() | |
} | |
const logoPath = vscode.Uri.file( | |
path.join(context.extensionPath, 'StackFinderLogo.png') | |
); | |
const logoSrc = panel.webview.asWebviewUri(logoPath); | |
await set_global_stack_questions_response(current_line_text) | |
if(global_questions.length == 0){ | |
global_current_language="" | |
await set_global_stack_questions_response(current_line_text) | |
} | |
const stack_questions = await build_html_body(logoSrc) | |
panel.webview.html = build_webview(stack_questions) | |
panel.webview.onDidReceiveMessage( | |
async message => { | |
if(message.command == "code"){ | |
activeEditor.edit(edit => { | |
let pos = new vscode.Position(activeEditor.selection.start.line, | |
activeEditor.selection.start.character) | |
edit.insert(pos, string_replacements_stack(message.text)); | |
google_analytics('send_code') | |
}); | |
// vscode.window.activeTerminal.show(); | |
// vscode.window.activeTerminal.sendText("hello world", false) | |
} | |
if(message.command == "next_page"){ | |
global_question_index += 1; | |
const new_html = await build_html_body(logoSrc) | |
panel.webview.html = build_webview(new_html) | |
}; | |
if(message.command == "previous_page"){ | |
global_question_index -= 1; | |
const new_html = await build_html_body(logoSrc) | |
panel.webview.html = build_webview(new_html) | |
}; | |
if(message.command == "change_page"){ | |
global_question_index = message.id; | |
const new_html = await build_html_body(logoSrc) | |
panel.webview.html = build_webview(new_html) | |
}; | |
}, | |
undefined, | |
context.subscriptions | |
); | |
}); | |
context.subscriptions.push(disposable); | |
} | |
function deactivate() {} | |
module.exports = { | |
activate, | |
deactivate | |
} | |
function build_webview(body_content){ | |
return `<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Title</title> | |
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/styles/a11y-dark.min.css"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/highlight.min.js"></script> | |
<script>hljs.highlightAll();</script> | |
<style> | |
a { | |
color: #E7B710; | |
} | |
a:hover { | |
color: #E1D89F; | |
} | |
h1, h2, h3, h4, h5, h6 { | |
margin-bottom: 15px; | |
margin-top: 0px; | |
padding-bottom: 0px; | |
padding-top: 0px; | |
} | |
body { | |
font-size: 1.0rem; | |
font-family:arial; | |
} | |
.btn { | |
text-decoration: none; | |
border: 1px solid rgb(146, 148, 248); | |
position: relative; | |
overflow: hidden; | |
background: none; | |
font-size: .70rem; | |
padding: .2rem .2rem; | |
color: #f4f4f4; | |
} | |
.btn:hover { | |
box-shadow: 1px 1px 10px 5px rgba(146, 148, 248, 0.4); | |
} | |
.btn:before { | |
content: ""; | |
position: absolute; | |
top: 0; | |
left: -100%; | |
width: 100%; | |
height: 100%; | |
background: linear-gradient( | |
120deg, | |
transparent, | |
rgba(146, 148, 248, 0.4), | |
transparent | |
); | |
transition: all 650ms; | |
} | |
.btn:hover:before { | |
left: 100%; | |
} | |
</style> | |
</head> | |
<body> | |
` + body_content + ` | |
<script> | |
const vscode = acquireVsCodeApi(); | |
$("button").click(function() { | |
if($(this).hasClass( "btn-send-to-editor" )){ | |
vscode.postMessage({command: 'code',text: $(this).next().next().html()}) | |
} | |
if($(this).hasClass( "btn-next-page" )){ | |
vscode.postMessage({command: 'next_page'}) | |
} | |
if($(this).hasClass( "btn-previous-page" )){ | |
vscode.postMessage({command: 'previous_page'}) | |
} | |
if($(this).hasClass( "btn-show-results" )){ | |
if($("#title_popup").css("display")=="none"){ | |
$("#title_popup").css("display", "block") | |
}else{ | |
$("#title_popup").css("display", "none") | |
} | |
}else{ | |
$("#title_popup").css("display", "none") | |
} | |
}); | |
$(".question").click(function() { | |
vscode.postMessage({command: 'change_page',id: $(this).attr("id")}) | |
$("#title_popup").css("display", "none") | |
}); | |
</script> | |
</body> | |
</html>` | |
} | |
function align_languages(){ | |
if(global_current_language == "plaintext"){ | |
global_current_language="" | |
} | |
if(global_current_language == "cpp"){ | |
global_current_language="c++" | |
} | |
if(global_current_language == "shellscript"){ | |
global_current_language="shell" | |
} | |
if(global_current_language == "cuda-cpp"){ | |
global_current_language="c++" | |
} | |
if(global_current_language == "csharp"){ | |
global_current_language="c#" | |
} | |
if(global_current_language == "fsharp"){ | |
global_current_language="f#" | |
} | |
if(global_current_language == "perl6"){ | |
global_current_language="perl" | |
} | |
if(global_current_language == "pip-requirements"){ | |
global_current_language="python" | |
} | |
if(global_current_language == "ignore"){ | |
global_current_language="" | |
} | |
if(global_current_language == "jsonc"){ | |
global_current_language="json" | |
} | |
if(global_current_language == "typescriptreact"){ | |
global_current_language="reactjs" | |
} | |
if(global_current_language == "javascriptreact"){ | |
global_current_language="reactjs" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment