Commit 786fcbce authored by Camil Staps's avatar Camil Staps 🚀

Resolve #148: index the common-problems repo on the frontend

parent 44910186
......@@ -9,3 +9,4 @@ node_modules/
backend/clean-compiler/
db/storage/
cache
frontend/common-problems.json
......@@ -6,7 +6,7 @@ WORKDIR /usr/src/cloogle
RUN install_clean.sh bundle-complete 2017-10-31 \
&& PACKAGES="patch" \
&& apt-get update -qq\
&& apt-get install -qq $PACKAGES --no-install-recommends \
&& apt-get install -qq $PACKAGES --no-install-recommends\
&& make distclean CloogleServer builddb\
&& rm -r /opt/clean/lib/*\
&& svn checkout https://svn.cs.ru.nl/repos/SoccerFun/src /opt/clean/lib/SoccerFun \
......
......@@ -7,8 +7,17 @@ RUN docker-php-source extract \
&& docker-php-ext-install sockets mysqli \
&& docker-php-source delete
COPY logo.svg /var/www/logo.svg
RUN cd /var/www \
&& apt-get update -qq \
&& apt-get install -qq imagemagick librsvg2-bin \
&& rsvg-convert -w 400 logo.svg > logo.png \
&& convert -resize 200x logo.png logo.png \
&& apt-get remove -qq imagemagick librsvg2-bin \
&& apt-get autoremove -qq
# Clean libraries, for /src
RUN apt-get update && apt-get install -y subversion ca-certificates git
RUN apt-get update -qq && apt-get install -qq subversion ca-certificates git
RUN mkdir -p /opt/clean && cd /opt/clean && \
curl -sSL ftp://ftp.cs.ru.nl/pub/Clean/builds/linux-x64/clean-bundle-complete-linux-x64-latest.tgz \
......@@ -33,17 +42,12 @@ RUN svn checkout https://svn.cs.ru.nl/repos/SoccerFun/src /opt/clean/lib/SoccerF
&& git clone https://github.com/clean-cloogle/StdEnv-doc /opt/clean/lib/StdEnv
# Pygments, for highlighting
RUN apt-get update \
&& apt-get install -y python3.5 python3-pip \
RUN apt-get update -qq \
&& apt-get install -qq python3.5 python3-pip \
&& pip3 install pygments pygments-lexer-clean
COPY index_common_problems.py .
RUN ./index_common_problems.py && rm index_common_problems.py
COPY iconv.sh .
RUN bash iconv.sh && rm iconv.sh
COPY logo.svg /var/www/logo.svg
RUN cd /var/www \
&& apt-get install -qq imagemagick librsvg2-bin \
&& rsvg-convert -w 400 logo.svg > logo.png \
&& convert -resize 200x logo.png logo.png \
&& apt-get remove -qq imagemagick librsvg2-bin \
&& apt-get autoremove -qq
......@@ -230,6 +230,8 @@ function makeExampleList(examples) {
}
function markupDocumentation(doc) {
doc = doc.replace(/\n```[^\n]+\n/g, '<pre>');
doc = doc.replace(/\n```\n/g, '</pre>');
doc = doc.replace(/\n\n/g, '<br class="parbreak"/>');
doc = doc.replace(/\n\s*-\s*/g, '<br/>- ');
doc = doc.replace(/{{`([^`}]+)`}}/g, '`{{$1}}`');
......@@ -378,7 +380,8 @@ function getResults(str, libs, include_builtins, include_core, include_apps, pag
var meta = [];
var hidden = [];
if ('langrep_documentation' in basic &&
if (typeof basic != 'undefined' &&
'langrep_documentation' in basic &&
basic['langrep_documentation'].length > 0) {
var doc = 'See the language report: ';
for (var i in basic['langrep_documentation']) {
......@@ -393,7 +396,7 @@ function getResults(str, libs, include_builtins, include_core, include_apps, pag
meta.push(doc);
}
if ('documentation' in basic)
if (typeof basic != 'undefined' && 'documentation' in basic)
meta.push(markupDocumentation(basic['documentation']));
switch (kind) {
......@@ -558,6 +561,24 @@ function getResults(str, libs, include_builtins, include_core, include_apps, pag
'<pre class="result-code">' + code + '</pre>' +
'</div>';
case 'ProblemResult':
result = result[1];
var solutions = '', examples = [];
for (var i in result.problem_solutions)
solutions += '<li>' + markupDocumentation(result.problem_solutions[i]) + '</li>';
for (var i in result.problem_examples)
examples += '<li>' + markupDocumentation(result.problem_examples[i]) + '</li>';
return '<div class="result">' +
'<div class="result-basic">Common problem: ' + result.problem_title + '</div>' +
'<div class="result-extra">' +
result.problem_description +
'<br/><br/>Possible solutions:<ul>' + solutions + '</ul>' +
'Examples:<ul>' + examples + '</ul>' +
'<a href="https://github.com/clean-cloogle/common-problems/blob/master/' + result.problem_key + '.md" target="_blank">Edit this explanation.</a><br/><br/>' +
'</div>' +
'<div class="result-code"></div>' +
'</div>';
default:
return '';
}
......@@ -587,33 +608,33 @@ function getResults(str, libs, include_builtins, include_core, include_apps, pag
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
document.getElementById('loading').remove();
var responsedata = JSON.parse(xmlHttp.responseText);
if (responsedata['return'] >= 0 && responsedata['return'] <= 64) {
for (var i = 0; i<responsedata['data'].length; i++) {
var c = responsedata['data'][i];
elem.innerHTML += makeResultHTML(c);
}
if (responsedata['return'] > 64) {
elem.innerHTML +=
'<p>Return code: ' + responsedata['return'] + ' (' + responsedata['msg'] + ')</p>';
}
var par = elem.parentNode;
if (responsedata['more_available'] != 0) {
par.innerHTML += '<div id="page-' + (page+1) + '">' +
'<p id="more" class="remove-at-request">' +
'<a href="javascript:getResults(null,null,null,null,null,' + (page+1) +
')">' + responsedata['more_available'] + ' more...</a></p>' +
'</div>';
}
for (var i = 0; i<responsedata['data'].length; i++) {
var c = responsedata['data'][i];
elem.innerHTML += makeResultHTML(c);
}
var par = elem.parentNode;
if ('more_available' in responsedata &&
responsedata['more_available'] != 0) {
par.innerHTML += '<div id="page-' + (page+1) + '">' +
'<p id="more" class="remove-at-request">' +
'<a href="javascript:getResults(null,null,null,null,null,' + (page+1) +
')">' + responsedata['more_available'] + ' more&#8230;<a></p>' +
'</div>';
}
par.innerHTML += '<div class="remove-at-request general-help">' + makeGeneralHelp(str) + '</span>';
par.innerHTML += '<div class="remove-at-request general-help">' + makeGeneralHelp(str) + '</span>';
if ('suggestions' in responsedata &&
responsedata['suggestions'].length > 0) {
par.innerHTML =
makeSuggestions(responsedata['suggestions'])
+ par.innerHTML;
}
} else {
elem.innerHTML =
'<p>Return code: ' + responsedata['return'] + '</p>' +
'<p>Message: ' + responsedata['msg'] + '</p>';
if ('suggestions' in responsedata &&
responsedata['suggestions'].length > 0) {
par.innerHTML =
makeSuggestions(responsedata['suggestions'])
+ par.innerHTML;
}
}
};
......
......@@ -12,6 +12,10 @@ define('DOS_MAX_BLOCK', 60);
if (file_exists('conf.php'))
require_once('conf.php');
$common_problems = [];
if (file_exists('common-problems.json'))
$common_problems = json_decode(file_get_contents('common-problems.json'), true);
$start_time = microtime(true);
if (defined('CLOOGLE_KEEP_STATISTICS')) {
......@@ -49,7 +53,7 @@ function has_database() {
function dos_protect() {
global $db, $ua_id, $ip;
if (!has_database)
if (!has_database())
return false;
$stmt = $db->prepare('SELECT COUNT(*) FROM `blacklist`
......@@ -150,6 +154,28 @@ if ($_SERVER['REQUEST_METHOD'] !== 'GET'){
$unify = isset($str[1]) ? trim($str[1]) : '';
$command = [];
$extra_results = [];
foreach ($common_problems as $problem) {
$match = false;
foreach ($problem['keywords'] as $kw) {
if (preg_match("/(?i)$kw/", $name) === 1) {
$match = true;
break;
}
}
if ($match) {
$extra_results[] = ['ProblemResult',
[ 'problem_key' => $problem['key']
, 'problem_title' => $problem['title']
, 'problem_description' => $problem['description']
, 'problem_solutions' => $problem['solutions']
, 'problem_examples' => $problem['examples']
]
];
}
}
if (substr($name, 0, 6) == 'class ') {
$command['className'] = substr($name, 6);
} elseif (substr($name, 0, 5) == 'type ') {
......@@ -188,22 +214,23 @@ if ($_SERVER['REQUEST_METHOD'] !== 'GET'){
$skt = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!socket_connect($skt, SERVER_HOSTNAME, SERVER_PORT)) {
respond(E_CLOOGLEDOWN, 'Cloogle server unreachable');
respond(E_CLOOGLEDOWN, 'Cloogle server unreachable', $extra_results);
} else {
$response = '';
socket_write($skt, json_encode($command));
$read = [$skt];
if (socket_select($read, $w = null, $e = null, SERVER_TIMEOUT) !== 1) {
respond(E_TIMEOUT, 'Connection to the Cloogle server timed out');
respond(E_TIMEOUT, 'Connection to the Cloogle server timed out', $extra_results);
} else {
while (($_response = socket_read($skt, 128, PHP_NORMAL_READ)) !== false) {
$response .= $_response;
if (strpos($_response, "\n") !== false)
break;
}
echo $response;
$decoded = json_decode($response, true);
log_request($decoded['return']);
$decoded['data'] = array_merge($extra_results, $decoded['data']);
echo json_encode($decoded);
}
socket_close($skt);
}
......
#!/usr/bin/env python3
import glob
import json
import re
from subprocess import call
def extract_keywords(lines):
keywords = [l[10:-1].split(';') for l in lines if l[:10] == 'Keywords: ']
keywords = sum(keywords, [])
keywords = [re.escape(kw.strip()).replace(r'\%', r'.*') for kw in keywords]
return keywords
def extract_description(lines):
desc = ''
reading = False
for l in lines:
if l[:3] == '## ':
break
if reading:
desc += l
if l[:10] == 'Keywords: ':
reading = True
return desc
def extract_solutions(lines):
sols = []
reading = False
for l in lines:
if l[:-1] == '## Examples':
break
if reading:
if l[:2] == '- ':
sols.append(l[2:-1])
elif l[:2] == ' ':
sols[-1] += ' ' + l[2:-1]
if l[:-1] == '## Solutions':
reading = True
return sols
def extract_examples(lines):
exs = ['']
reading = False
for l in lines:
if reading:
if l[:-1] == '---':
exs.append('')
else:
exs[-1] += l
if l[:-1] == '## Examples':
reading = True
return [ex for ex in exs]
def index(fname):
with open(fname, 'r') as f:
lines = f.readlines()
title = lines[0][2:-1]
keywords = extract_keywords(lines)
description = extract_description(lines)
solutions = extract_solutions(lines)
examples = extract_examples(lines)
return {
'key': fname[:-3],
'title': title,
'keywords': keywords,
'description': description,
'solutions': solutions,
'examples': examples
}
if __name__ == '__main__':
call(['git', 'clone', 'https://github.com/clean-cloogle/common-problems'])
problems = []
for f in glob.glob('common-problems/*.md'):
if f != 'README.md':
problems.append(index(f))
with open('common-problems.json', 'w') as f:
f.write(json.dumps(problems))
call(['rm', '-r', '-f', 'common-problems'])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment