feat(problem): insert pdf in statement
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Baoshuo Ren 2023-01-30 20:27:53 +08:00
parent 24c5ad4e5f
commit 5f7bf17fe0
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
12 changed files with 206 additions and 33 deletions

View File

@ -98,6 +98,12 @@ $new_remote_problem_form->handle = function (&$vdata) {
]); ]);
$id = DB::insert_id(); $id = DB::insert_id();
dataNewProblem($id);
if ($data['type'] == 'pdf') {
file_put_contents(UOJContext::storagePath() , "/problem_resources/$id/statement.pdf", $data['pdf_data']);
$data['statement'] = "<div data-pdf data-src=\"/problem/$id/resources/statement.pdf\"></div>\n" . $data['statement'];
}
DB::insert([ DB::insert([
"insert into problems_contents", "insert into problems_contents",
@ -105,7 +111,6 @@ $new_remote_problem_form->handle = function (&$vdata) {
"values", "values",
DB::tuple([$id, HTML::purifier(['a' => ['target' => 'Enum#_blank']])->purify($data['statement']), '', '']) DB::tuple([$id, HTML::purifier(['a' => ['target' => 'Enum#_blank']])->purify($data['statement']), '', ''])
]); ]);
dataNewProblem($id);
DB::insert([ DB::insert([
"insert into problems_tags", "insert into problems_tags",

View File

@ -2,6 +2,7 @@
requireLib('bootstrap5'); requireLib('bootstrap5');
requireLib('hljs'); requireLib('hljs');
requireLib('mathjax'); requireLib('mathjax');
requireLib('pdf.js');
requirePHPLib('form'); requirePHPLib('form');
requirePHPLib('judger'); requirePHPLib('judger');

View File

@ -144,6 +144,11 @@ if (UOJProblem::info('type') == 'remote') {
], ],
]); ]);
if ($data['type'] == 'pdf') {
file_put_contents(UOJContext::storagePath() . "/problem_resources/" . UOJProblem::info('id') . "/statement.pdf", $data['pdf_data']);
$data['statement'] = '<div data-pdf data-src="/problem/' . UOJProblem::info('id') . '/resources/statement.pdf"></div>' . "\n" . $data['statement'];
}
DB::update([ DB::update([
"update problems_contents", "update problems_contents",
"set", [ "set", [

View File

@ -436,6 +436,10 @@ class HTML {
$def->addElement('footer', 'Block', 'Flow', 'Common'); $def->addElement('footer', 'Block', 'Flow', 'Common');
mergeConfig($extra_allowed_html, [ mergeConfig($extra_allowed_html, [
'div' => [
'data-pdf' => 'Text',
'data-src' => 'URI',
],
'span' => [ 'span' => [
'class' => 'Enum#uoj-username', 'class' => 'Enum#uoj-username',
'data-realname' => 'Text', 'data-realname' => 'Text',

View File

@ -129,8 +129,10 @@ class UOJBlogEditor {
$elements = $dom->getElementsByTagName('li'); $elements = $dom->getElementsByTagName('li');
foreach ($elements as $element) { foreach ($elements as $element) {
$element->setAttribute('class', $element->setAttribute(
$element->getAttribute('class') . ' fragment'); 'class',
$element->getAttribute('class') . ' fragment'
);
} }
return $purifier->purify($dom->saveHTML()); return $purifier->purify($dom->saveHTML());
@ -181,7 +183,10 @@ class UOJBlogEditor {
if (isset($_POST['need_preview'])) { if (isset($_POST['need_preview'])) {
ob_start(); ob_start();
if ($this->type == 'blog') { if ($this->type == 'blog') {
$req_lib = array('mathjax' => ''); $req_lib = [
'mathjax' => '',
'pdf.js' => '',
];
if (isset($REQUIRE_LIB['bootstrap5'])) { if (isset($REQUIRE_LIB['bootstrap5'])) {
$req_lib['bootstrap5'] = ''; $req_lib['bootstrap5'] = '';

View File

@ -7,9 +7,12 @@ class UOJMarkdown extends ParsedownMath {
$this->options['username_with_color'] = $options['username_with_color'] ?: false; $this->options['username_with_color'] = $options['username_with_color'] ?: false;
// Special Block
$this->inlineMarkerList .= '@';
$this->InlineTypes['@'][] = 'SpecialBlock';
// https://gist.github.com/ShNURoK42/b5ce8baa570975db487c // https://gist.github.com/ShNURoK42/b5ce8baa570975db487c
$this->InlineTypes['@'][] = 'UserMention'; $this->InlineTypes['@'][] = 'UserMention';
$this->inlineMarkerList .= '@';
} }
// https://github.com/taufik-nurrohman/parsedown-extra-plugin/blob/1653418c5a9cf5277cd28b0b23ba2d95d18e9bc4/ParsedownExtraPlugin.php#L340-L345 // https://github.com/taufik-nurrohman/parsedown-extra-plugin/blob/1653418c5a9cf5277cd28b0b23ba2d95d18e9bc4/ParsedownExtraPlugin.php#L340-L345
@ -85,4 +88,35 @@ class UOJMarkdown extends ParsedownMath {
]; ];
} }
} }
protected function inlineSpecialBlock($Excerpt) {
if (!isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[') {
return;
}
$Excerpt['text'] = substr($Excerpt['text'], 1);
$Link = $this->inlineLink($Excerpt);
if ($Link === null) {
return;
}
$Inline = [
'extent' => $Link['extent'] + 1,
'element' => [
'name' => 'div',
'attributes' => [
'data-src' => $Link['element']['attributes']['href'],
"data-{$Link['element']['text']}" => $Link['element']['text'],
],
],
];
$Inline['element']['attributes'] += $Link['element']['attributes'];
unset($Inline['element']['attributes']['href']);
return $Inline;
}
} }

View File

@ -196,13 +196,14 @@ class UOJRemoteProblem {
'time_limit' => null, 'time_limit' => null,
'memory_limit' => null, 'memory_limit' => null,
'difficulty' => -1, 'difficulty' => -1,
'pdf_data' => $res['response'],
'statement' => HTML::tag('h3', [], '提示') . 'statement' => HTML::tag('h3', [], '提示') .
HTML::tag( HTML::tag(
'p', 'p',
[], [],
'本题题面为 PDF 题面,请' . '若无法正常加载 PDF,请' .
HTML::tag('a', ['href' => static::getCodeforcesProblemUrl($id), 'target' => '_blank'], '点此') . HTML::tag('a', ['href' => static::getCodeforcesProblemUrl($id), 'target' => '_blank'], '点此') .
'查看题面。' '查看题面。'
), ),
]; ];
} else { } else {

View File

@ -265,6 +265,54 @@ if (!isset($ShowPageHeader)) {
<?= HTML::css_link('/css/font-awesome.min.css') ?> <?= HTML::css_link('/css/font-awesome.min.css') ?>
<?php endif ?> <?php endif ?>
<?php if (isset($REQUIRE_LIB['pdf.js'])) : ?>
<!-- pdf.js -->
<?= HTML::js_src('/js/pdf.js') ?>
<script>
pdfjsLib.GlobalWorkerOptions.workerSrc = '/js/pdf.worker.js';
function randstr(prefix) {
return Math.random().toString(36).replace('0.', prefix || '');
}
$(document).ready(function() {
$('div[data-pdf]').each(function() {
var _this = $(this);
var pdf_src = $(this).data('src');
$(this).css('width', '100%').css('height', '100%');
var task = pdfjsLib.getDocument(pdf_src);
var id = 'pdf_' + task.docId;
$(this).attr('id', id + '_container');
task.promise.then(function(pdf) {
for (var i = 1; i <= pdf.numPages; i++) {
$(_this).append('<canvas id="' + id + '_page_' + i + '" class="pdf-page-canvas"></canvas>');
pdf.getPage(i).then(function(page) {
var viewport = page.getViewport({
scale: 2,
});
var canvas = document.getElementById(id + '_page_' + page.pageNumber);
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({
canvasContext: canvas.getContext('2d'),
viewport: viewport,
});
});
}
});
});
});
</script>
<?php endif ?>
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>

View File

@ -238,6 +238,10 @@ h6,
margin-bottom: 1em; margin-bottom: 1em;
} }
.pdf-page-canvas {
width: 100% !important;
}
form.uoj-bs4-form-inline { form.uoj-bs4-form-inline {
display: inline-block; display: inline-block;
margin-right: 0.3em; margin-right: 0.3em;

22
web/js/pdf.js Normal file

File diff suppressed because one or more lines are too long

22
web/js/pdf.sandbox.js Normal file

File diff suppressed because one or more lines are too long

22
web/js/pdf.worker.js vendored Normal file

File diff suppressed because one or more lines are too long