1
0

Added ProjectLawful-ebook downloads (blog::29)
All checks were successful
Build Docker and Deploy / Build Docker (push) Successful in 1m18s
Build Docker and Deploy / Deploy to Server (push) Successful in 27s

This commit is contained in:
Mike Schwörer 2023-09-11 19:59:07 +02:00
parent f7688a224b
commit 300992b49f
Signed by: Mikescher
GPG Key ID: D3C7172E0A70F8CF
49 changed files with 689 additions and 84 deletions

View File

@ -6,10 +6,11 @@
<State> <State>
<option name="id" value="b1f51636-21bf-4ca9-a884-b0419489ab5f" /> <option name="id" value="b1f51636-21bf-4ca9-a884-b0419489ab5f" />
<option name="name" value="EGG DB" /> <option name="name" value="EGG DB" />
<option name="languageId" value="SQLite" /> <option name="dbmsName" value="SQLITE" />
<option name="urls"> <option name="urls">
<array> <array>
<option value="file://$PROJECT_DIR$/www/extern/egg/db_init.sql" /> <option value="file://$PROJECT_DIR$/www/extern/egg/db_init.sql" />
<option value="file://$PROJECT_DIR$/data/schema.sql" />
</array> </array>
</option> </option>
</State> </State>

1
.idea/sqldialects.xml generated
View File

@ -2,6 +2,7 @@
<project version="4"> <project version="4">
<component name="SqlDialectMappings"> <component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$" dialect="MySQL" /> <file url="file://$PROJECT_DIR$" dialect="MySQL" />
<file url="file://$PROJECT_DIR$/data/schema.sql" dialect="SQLite" />
<file url="file://$PROJECT_DIR$/www/extern/egg" dialect="SQLite" /> <file url="file://$PROJECT_DIR$/www/extern/egg" dialect="SQLite" />
<file url="PROJECT" dialect="MySQL" /> <file url="PROJECT" dialect="MySQL" />
</component> </component>

View File

@ -58,3 +58,14 @@ CREATE TABLE IF NOT EXISTS updateslog
PRIMARY KEY (ID) PRIMARY KEY (ID)
); );
CREATE TABLE IF NOT EXISTS projectlawful_downloadcounter
(
id int(11) NOT NULL AUTO_INCREMENT,
variant varchar(512) NOT NULL DEFAULT '0',
timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
ip varchar(128) NOT NULL,
useragent varchar(4096) NOT NULL,
PRIMARY KEY (ID)
);

View File

@ -1156,7 +1156,7 @@ html, body {
background: transparent !important; background: transparent !important;
} }
.blogcontent_euler, .blogcontent_markdown, .blogcontent_plain { .blogcontent_euler, .blogcontent_markdown, .blogcontent_plain, .blogcontent_aoclist, .blogcontent_html {
width: 90%; width: 90%;
} }
@ -2612,5 +2612,100 @@ html, body {
height: 150px; height: 150px;
} }
} }
.project-lawful-ebook-blogpost code {
background-color: rgba(0, 0, 0, 0.1);
border-radius: 2px;
padding-left: 2px;
padding-right: 2px;
}
.project-lawful-ebook-blogpost .variant {
display: grid;
grid-template-columns: repeat(6, auto) 1fr;
grid-template-rows: auto auto;
grid-column-gap: 1rem;
}
.project-lawful-ebook-blogpost .variant h3 {
grid-row: 1;
grid-column: 1/-1;
text-decoration: underline;
}
.project-lawful-ebook-blogpost .variant .dlbutton {
position: relative;
height: 100%;
padding: 0;
display: flex;
border: none;
}
.project-lawful-ebook-blogpost .variant .dlbutton img {
opacity: 0;
pointer-events: none;
user-select: none;
}
.project-lawful-ebook-blogpost .variant .dlbutton a {
display: grid;
grid-template-rows: 1fr auto auto;
grid-row-gap: 4px;
justify-content: center;
align-items: center;
justify-items: center;
padding: 0.5rem;
cursor: pointer;
text-decoration: none;
color: #DDDDDD;
background-color: #222222;
border-radius: 4px;
border: 1px solid black;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.project-lawful-ebook-blogpost .variant .dlbutton a:hover {
background-color: #555555;
}
.project-lawful-ebook-blogpost .variant .dlbutton a .span_dl {
font-weight: bold;
font-size: 1.33em;
}
.project-lawful-ebook-blogpost .variant .dlbutton a .span_mb {
font-size: 0.75em;
}
.project-lawful-ebook-blogpost .variant .dlbutton svg {
fill: #BBB;
}
.project-lawful-ebook-blogpost .variant img {
width: 100%;
border: 1px solid #555;
}
.project-lawful-ebook-blogpost .variant.alt-variants {
display: flex;
flex-direction: column;
gap: 4px;
}
.project-lawful-ebook-blogpost .dlbtn_alt {
display: grid;
grid-template-columns: 24px auto 1fr auto;
grid-column-gap: 1rem;
color: #DDDDDD;
background-color: #222222;
border: 1px solid black;
border-radius: 4px;
text-decoration: none;
cursor: pointer;
padding: 6px;
align-items: center;
}
.project-lawful-ebook-blogpost .dlbtn_alt:hover {
background-color: #555555;
}
.project-lawful-ebook-blogpost .dlbtn_alt svg {
fill: #BBB;
}
.project-lawful-ebook-blogpost .dlbtn_alt .span_mb {
font-size: 0.75em;
grid-column: 4;
}
/*# sourceMappingURL=styles.css.map */ /*# sourceMappingURL=styles.css.map */

View File

@ -217,7 +217,7 @@ html,body{margin:0;padding:0;height:100%}
.mdtable_container{overflow-x:auto} .mdtable_container{overflow-x:auto}
.notable{width:unset !important;border:none !important} .notable{width:unset !important;border:none !important}
.notable th,.notable td,.notable tr{border:none !important;background:transparent !important} .notable th,.notable td,.notable tr{border:none !important;background:transparent !important}
.blogcontent_euler,.blogcontent_markdown,.blogcontent_plain{width:90%} .blogcontent_euler,.blogcontent_markdown,.blogcontent_plain,.blogcontent_aoclist,.blogcontent_html{width:90%}
#PEB_tableProblems .PEB_tablerowProblems:hover{background-color:#999} #PEB_tableProblems .PEB_tablerowProblems:hover{background-color:#999}
#PEB_tableProblems .PEB_TC_Value{font-family:Consolas,Monaco,"Courier New",Menlo,monospace} #PEB_tableProblems .PEB_TC_Value{font-family:Consolas,Monaco,"Courier New",Menlo,monospace}
#PEB_tableProblems .PEB_TC_Value:not(:hover){color:transparent;-o-transition:.5s;-ms-transition:.5s;-moz-transition:.5s;-webkit-transition:.5s;transition:.5s} #PEB_tableProblems .PEB_TC_Value:not(:hover){color:transparent;-o-transition:.5s;-ms-transition:.5s;-moz-transition:.5s;-webkit-transition:.5s;transition:.5s}
@ -495,3 +495,19 @@ html,body{margin:0;padding:0;height:100%}
.bce_code_out .bce_code_out_left{flex-grow:0;height:100px} .bce_code_out .bce_code_out_left{flex-grow:0;height:100px}
.bce_code_out .bce_code_out_right{width:auto;height:150px} .bce_code_out .bce_code_out_right{width:auto;height:150px}
} }
.project-lawful-ebook-blogpost code{background-color:rgba(0,0,0,0.1);border-radius:2px;padding-left:2px;padding-right:2px}
.project-lawful-ebook-blogpost .variant{display:grid;grid-template-columns:repeat(6,auto) 1fr;grid-template-rows:auto auto;grid-column-gap:1rem}
.project-lawful-ebook-blogpost .variant h3{grid-row:1;grid-column:1/-1;text-decoration:underline}
.project-lawful-ebook-blogpost .variant .dlbutton{position:relative;height:100%;padding:0;display:flex;border:0}
.project-lawful-ebook-blogpost .variant .dlbutton img{opacity:0;pointer-events:none;user-select:none}
.project-lawful-ebook-blogpost .variant .dlbutton a{display:grid;grid-template-rows:1fr auto auto;grid-row-gap:4px;justify-content:center;align-items:center;justify-items:center;padding:.5rem;cursor:pointer;text-decoration:none;color:#ddd;background-color:#222;border-radius:4px;border:1px solid black;position:absolute;left:0;right:0;top:0;bottom:0}
.project-lawful-ebook-blogpost .variant .dlbutton a:hover{background-color:#555}
.project-lawful-ebook-blogpost .variant .dlbutton a .span_dl{font-weight:bold;font-size:1.33em}
.project-lawful-ebook-blogpost .variant .dlbutton a .span_mb{font-size:.75em}
.project-lawful-ebook-blogpost .variant .dlbutton svg{fill:#BBB}
.project-lawful-ebook-blogpost .variant img{width:100%;border:1px solid #555}
.project-lawful-ebook-blogpost .variant.alt-variants{display:flex;flex-direction:column;gap:4px}
.project-lawful-ebook-blogpost .dlbtn_alt{display:grid;grid-template-columns:24px auto 1fr auto;grid-column-gap:1rem;color:#ddd;background-color:#222;border:1px solid black;border-radius:4px;text-decoration:none;cursor:pointer;padding:6px;align-items:center}
.project-lawful-ebook-blogpost .dlbtn_alt:hover{background-color:#555}
.project-lawful-ebook-blogpost .dlbtn_alt svg{fill:#BBB}
.project-lawful-ebook-blogpost .dlbtn_alt .span_mb{font-size:.75em;grid-column:4}

View File

@ -29,3 +29,5 @@
@import 'styles_bfjoustrunner'; @import 'styles_bfjoustrunner';
@import 'styles_befungerunner'; @import 'styles_befungerunner';
@import 'styles_projectlawfulebook.scss';

View File

@ -56,4 +56,4 @@
} }
} }
.blogcontent_euler, .blogcontent_markdown, .blogcontent_plain { width: 90%;} .blogcontent_euler, .blogcontent_markdown, .blogcontent_plain, .blogcontent_aoclist, .blogcontent_html { width: 90%;}

View File

@ -0,0 +1,123 @@
@import 'styles_config';
.project-lawful-ebook-blogpost
{
code {
background-color: rgba(0, 0, 0, 0.1);
border-radius: 2px;
padding-left: 2px;
padding-right: 2px;
}
.variant {
display: grid;
grid-template-columns: repeat(6, auto) 1fr;
grid-template-rows: auto auto;
grid-column-gap: 1rem;
}
.variant h3 { grid-row: 1; grid-column: 1/-1; text-decoration: underline; }
.variant .dlbutton {
position: relative;
height: 100%;
padding: 0;
display: flex;
border:none;
}
.variant .dlbutton img {
opacity: 0;
pointer-events: none;
user-select: none;
}
.variant .dlbutton a {
display: grid;
grid-template-rows: 1fr auto auto;
grid-row-gap: 4px;
justify-content: center;
align-items: center;
justify-items: center;
padding: 0.5rem;
cursor: pointer;
text-decoration: none;
color: $COL_BUTTON_GENERIC_FG;
background-color: $COL_BUTTON_GENERIC_BG;
border-radius: 4px;
border: 1px solid black;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.variant .dlbutton a:hover {
background-color: $COL_BUTTON_GENERIC_HOVER;
}
.variant .dlbutton a .span_dl {
font-weight: bold;
font-size: 1.33em;
}
.variant .dlbutton a .span_mb {
font-size: 0.75em;
}
.variant .dlbutton svg {
fill: #BBB;
}
.variant img {
width: 100%;
border: 1px solid #555;
}
}
.project-lawful-ebook-blogpost
{
.variant.alt-variants {
display: flex;
flex-direction: column;
gap: 4px;
}
.dlbtn_alt {
display: grid;
grid-template-columns: 24px auto 1fr auto;
grid-column-gap: 1rem;
color: $COL_BUTTON_GENERIC_FG;
background-color: $COL_BUTTON_GENERIC_BG;
border: 1px solid black;
border-radius: 4px;
text-decoration: none;
cursor: pointer;
padding: 6px;
align-items: center;
}
.dlbtn_alt:hover {
background-color: $COL_BUTTON_GENERIC_HOVER;
}
.dlbtn_alt svg {
fill: #BBB;
}
.dlbtn_alt .span_mb {
font-size: 0.75em;
grid-column: 4;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

4
www/data/projectlawful/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*.epub
*.mobi
*.zip
*.html

View File

View File

@ -19,7 +19,7 @@ $FRAME_OPTIONS->alternative_url = "/adventofcode/$year";
?> ?>
<div class="boxedcontent blogcontent_plain"> <div class="boxedcontent blogcontent_aoclist">
<div style="position: relative;"> <div style="position: relative;">
<a href="<?php echo $SITE->modules->AdventOfCode()->getGithubLink($year); ?>" style="position: absolute; top: 0; right: 0; border: 0;"> <a href="<?php echo $SITE->modules->AdventOfCode()->getGithubLink($year); ?>" style="position: absolute; top: 0; right: 0; border: 0;">

View File

@ -0,0 +1,35 @@
<?php
require_once (__DIR__ . '/../internals/website.php');
/** @var PageFrameOptions $FRAME_OPTIONS */ global $FRAME_OPTIONS;
/** @var URLRoute $ROUTE */ global $ROUTE;
/** @var Website $SITE */ global $SITE;
global $FRAGMENT_PARAM;
/** @var array $parameter */
$parameter = $FRAGMENT_PARAM;
?>
<?php
$post = $parameter['blogpost'];
?>
<div class="boxedcontent blogcontent_html">
<?php if (isset($post['extras']['gh_link'])): ?>
<div style="position: relative;">
<a href="<?= $post['extras']['gh_link'] ?>" style="position: absolute; top: 0; right: 0; border: 0;">
<img src="/data/images/blog/github_band.png" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png">
</a>
</div>
<?php endif; ?>
<div class="bc_header">
<?php echo $post['date']; ?>
</div>
<div class="bc_data">
<?php echo $SITE->modules->Blog()->getPostFragment($post); ?>
</div>
</div>

View File

@ -49,6 +49,8 @@ $URL_RULES =
[ 'url' => ['admin'], 'target' => 'admin.php', 'options' => [ 'password' ], 'parameter' => [ ] ], [ 'url' => ['admin'], 'target' => 'admin.php', 'options' => [ 'password' ], 'parameter' => [ ] ],
[ 'url' => ['blog','29','*','download','?{variant}'], 'target' => 'projectlawful_download.php', 'options' => [ ], 'parameter' => [ 'variant' => '%URL%' ], ],
[ 'url' => ['blog'], 'target' => 'blog_list.php', 'options' => [ ], 'parameter' => [ ], ], [ 'url' => ['blog'], 'target' => 'blog_list.php', 'options' => [ ], 'parameter' => [ ], ],
[ 'url' => ['log'], 'target' => 'blog_list.php', 'options' => [ ], 'parameter' => [ ], ], [ 'url' => ['log'], 'target' => 'blog_list.php', 'options' => [ ], 'parameter' => [ ], ],
[ 'url' => ['blogpost', 'index'], 'target' => 'blog_list.php', 'options' => [ ], 'parameter' => [ ], ], [ 'url' => ['blogpost', 'index'], 'target' => 'blog_list.php', 'options' => [ ], 'parameter' => [ ], ],

View File

@ -75,6 +75,14 @@ class Fragments
]); ]);
} }
public function BlogviewHTML(array $blogpost)
{
return $this->evalFragment('BlogviewHTML', 'blogview_html.php',
[
'blogpost' => $blogpost,
]);
}
public function BlogviewEulerList(array $blogpost) public function BlogviewEulerList(array $blogpost)
{ {
return $this->evalFragment('BlogviewEulerList', 'blogview_euler_list.php', return $this->evalFragment('BlogviewEulerList', 'blogview_euler_list.php',

View File

@ -1,5 +1,7 @@
<?php <?php
use internals\modules\ProjectLawful;
require_once 'website.php'; require_once 'website.php';
class Modules class Modules
@ -16,6 +18,7 @@ class Modules
/** @var MikescherGitGraph|null */ private $extendedgitgraph = null; /** @var MikescherGitGraph|null */ private $extendedgitgraph = null;
/** @var Highscores|null */ private $highscores = null; /** @var Highscores|null */ private $highscores = null;
/** @var SelfTest|null */ private $selftest = null; /** @var SelfTest|null */ private $selftest = null;
/** @var ProjectLawful|null */ private $projectlawful = null;
/** @var Website */ /** @var Website */
private $site; private $site;
@ -96,4 +99,10 @@ class Modules
if ($this->selftest === null) { require_once 'modules/selftest.php'; $this->selftest = new SelfTest(); } if ($this->selftest === null) { require_once 'modules/selftest.php'; $this->selftest = new SelfTest(); }
return $this->selftest; return $this->selftest;
} }
public function ProjectLawful(): ProjectLawful
{
if ($this->projectlawful === null) { require_once 'modules/projectlawful.php'; $this->projectlawful = new ProjectLawful($this->site); }
return $this->projectlawful;
}
} }

View File

@ -120,6 +120,10 @@ class Blog implements IWebsiteModule
} else if ($post['type'] === 'plain') { } else if ($post['type'] === 'plain') {
if (!file_exists($post['file_fragment'])) return ['result'=>'err', 'message' => 'Fragment not found ' . $post['fragment']];
} else if ($post['type'] === 'html') {
if (!file_exists($post['file_fragment'])) return ['result'=>'err', 'message' => 'Fragment not found ' . $post['fragment']]; if (!file_exists($post['file_fragment'])) return ['result'=>'err', 'message' => 'Fragment not found ' . $post['fragment']];
} else if ($post['type'] === 'euler') { } else if ($post['type'] === 'euler') {

View File

@ -0,0 +1,76 @@
<?php
namespace internals\modules;
use IWebsiteModule;
use PDO;
use Throwable;
use Website;
class ProjectLawful implements IWebsiteModule
{
/** @var Website */
private $site;
public $variants = [
'avatars-moreinfo' => 'project-lawful-avatars-moreinfo.epub',
'avatars' => 'project-lawful-avatars.epub',
'biggerhtml' => 'project-lawful-biggerhtml.epub',
'inline' => 'project-lawful-inline.epub',
'moreinfo' => 'project-lawful-moreinfo.epub',
'onlymainstory-avatars-moreinfo' => 'project-lawful-onlymainstory-avatars-moreinfo.epub',
'onlymainstory-avatars' => 'project-lawful-onlymainstory-avatars.epub',
'onlymainstory-biggerhtml' => 'project-lawful-onlymainstory-biggerhtml.epub',
'onlymainstory-inline' => 'project-lawful-onlymainstory-inline.epub',
'onlymainstory-moreinfo' => 'project-lawful-onlymainstory-moreinfo.epub',
'sfw-avatars-moreinfo' => 'project-lawful-sfw-avatars-moreinfo.epub',
'sfw-avatars' => 'project-lawful-sfw-avatars.epub',
'sfw-biggerhtml' => 'project-lawful-sfw-biggerhtml.epub',
'sfw-inline' => 'project-lawful-sfw-inline.epub',
'sfw-moreinfo' => 'project-lawful-sfw-moreinfo.epub',
];
public function __construct(Website $site)
{
$this->site = $site;
}
public function insertDownload($variant)
{
try
{
$this->site->modules->Database()->sql_query_assoc_prep('INSERT INTO projectlawful_downloadcounter (variant, ip, useragent) VALUES (:vr, :ip, :ua)',
[
[':vr', $variant, PDO::PARAM_STR],
[':ip', get_client_ip(), PDO::PARAM_STR],
[':ua', $_SERVER['HTTP_USER_AGENT'] ?? '', PDO::PARAM_STR],
]);
return true;
}
catch (Throwable $t)
{
return false;
}
}
public function listDownloadCounts()
{
return $this->site->modules->Database()->sql_query_assoc('SELECT variant, COUNT(*) AS `count` FROM projectlawful_downloadcounter GROUP BY variant ORDER BY variant');
}
public function variantExists(string $variant)
{
return isset($this->variants[$variant]);
}
public function checkConsistency()
{
foreach ($this->variants as $key => $val) {
$fn = __DIR__ . '/../../data/projectlawful/'.$val;
if (!file_exists($fn)) {
return ['result'=>'err', 'message' => 'File not found: ' . $fn];
}
}
return ['result' => 'ok', 'message' => ''];
}
}

View File

@ -30,6 +30,7 @@ class SelfTest implements IWebsiteModule
'modules::updateslog' => 'Program Updates (data)', 'modules::updateslog' => 'Program Updates (data)',
'modules::webapps' => 'Webapps (data)', 'modules::webapps' => 'Webapps (data)',
'modules::highscores' => 'Highscores (data)', 'modules::highscores' => 'Highscores (data)',
'modules::projectlawful' => 'ProjectLawful-ebook (files)',
'egg::db-check' => 'ExtendedGitGraph (db-check)', 'egg::db-check' => 'ExtendedGitGraph (db-check)',
'backend::git' => 'Git Repository', 'backend::git' => 'Git Repository',
]; ];
@ -118,6 +119,7 @@ class SelfTest implements IWebsiteModule
$this->addCheckConsistency("modules::updateslog::updateslog-check-consistency", function(){ return Website::inst()->modules->UpdatesLog(); }); $this->addCheckConsistency("modules::updateslog::updateslog-check-consistency", function(){ return Website::inst()->modules->UpdatesLog(); });
$this->addCheckConsistency("modules::webapps::webapps-check-consistency", function(){ return Website::inst()->modules->WebApps(); }); $this->addCheckConsistency("modules::webapps::webapps-check-consistency", function(){ return Website::inst()->modules->WebApps(); });
$this->addCheckConsistency("modules::highscores::highscores-check-consistency", function(){ return Website::inst()->modules->Highscores(); }); $this->addCheckConsistency("modules::highscores::highscores-check-consistency", function(){ return Website::inst()->modules->Highscores(); });
$this->addCheckConsistency("modules::projectlawful::projectlawful-check-consistency", function(){ return Website::inst()->modules->ProjectLawful(); });
$this->addLambdaStatus("egg::db-check::check-db-consistency", function(){ return Website::inst()->modules->ExtendedGitGraph()->checkDatabaseConsistency(); }); $this->addLambdaStatus("egg::db-check::check-db-consistency", function(){ return Website::inst()->modules->ExtendedGitGraph()->checkDatabaseConsistency(); });

View File

@ -92,6 +92,18 @@ $connected = true; try { $SITE->modules->Database(); } catch (Exception $e) { $c
<!-- - - - - - - - - - - - - - - - - - - - - --> <!-- - - - - - - - - - - - - - - - - - - - - -->
<div class="boxedcontent">
<div class="bc_header">Project Lawful ebook (download count)</div>
<div class="bc_data keyvaluelist kvl_250">
<?php foreach ($SITE->modules->ProjectLawful()->listDownloadCounts() as $dlc): ?>
<div><span><?php echo $dlc['variant']; ?>:</span> <span><?php echo $dlc['count']; ?></span></div>
<?php endforeach; ?>
</div>
</div>
<!-- - - - - - - - - - - - - - - - - - - - - -->
<div class="boxedcontent"> <div class="boxedcontent">
<div class="bc_header">ExtendedGitGraph</div> <div class="bc_header">ExtendedGitGraph</div>

View File

@ -39,6 +39,10 @@ else
{ {
echo $SITE->fragments->BlogviewMarkdown($post); echo $SITE->fragments->BlogviewMarkdown($post);
} }
elseif ($post['type'] === 'html')
{
echo $SITE->fragments->BlogviewHTML($post);
}
elseif ($post['type'] === 'euler') elseif ($post['type'] === 'euler')
{ {
if ($subview === '') echo $SITE->fragments->BlogviewEulerList($post); if ($subview === '') echo $SITE->fragments->BlogviewEulerList($post);

View File

@ -51,7 +51,7 @@ $FRAME_OPTIONS->activeHeader = 'programs';
{ {
if ($xurl['alert'] === null) if ($xurl['alert'] === null)
{ {
echo '<a class="iconbutton '.$xurl['css'].'" href="'.$xurl['href'].'">'; echo '<a rel="nofollow" class="iconbutton '.$xurl['css'].'" href="'.$xurl['href'].'">';
echo '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">'; echo '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">';
echo '<use xlink:href="/data/images/icons.svg#'.$xurl['svg'].'"/>'; echo '<use xlink:href="/data/images/icons.svg#'.$xurl['svg'].'"/>';
echo '</svg>'; echo '</svg>';

View File

@ -0,0 +1,18 @@
<?php
require_once (__DIR__ . '/../internals/website.php');
/** @var PageFrameOptions $FRAME_OPTIONS */ global $FRAME_OPTIONS;
/** @var URLRoute $ROUTE */ global $ROUTE;
/** @var Website $SITE */ global $SITE;
$variant = $ROUTE->parameter['variant'];
if (!$SITE->modules->ProjectLawful()->variantExists($variant))
{
$FRAME_OPTIONS->setForced404('epub file not found');
return;
}
$SITE->modules->ProjectLawful()->insertDownload($variant);
$FRAME_OPTIONS->setForcedRedirect('/data/projectlawful/project-lawful-' . $variant . '.epub');

View File

@ -30,4 +30,5 @@ return
[ 'id' => 26, 'date' => '2020-12-01', 'visible' => true, 'title' => 'Advent of Code 2020 - Rust', 'fragment' => 'aoc2020.md', 'type' => 'aoc', 'cat' => 'blog', 'extras' => ['aoc:year' => '2020'] ], [ 'id' => 26, 'date' => '2020-12-01', 'visible' => true, 'title' => 'Advent of Code 2020 - Rust', 'fragment' => 'aoc2020.md', 'type' => 'aoc', 'cat' => 'blog', 'extras' => ['aoc:year' => '2020'] ],
[ 'id' => 27, 'date' => '2021-11-25', 'visible' => true, 'title' => 'Advent of Code 2021 - Go', 'fragment' => 'aoc2021.md', 'type' => 'aoc', 'cat' => 'blog', 'extras' => ['aoc:year' => '2021'] ], [ 'id' => 27, 'date' => '2021-11-25', 'visible' => true, 'title' => 'Advent of Code 2021 - Go', 'fragment' => 'aoc2021.md', 'type' => 'aoc', 'cat' => 'blog', 'extras' => ['aoc:year' => '2021'] ],
[ 'id' => 28, 'date' => '2022-12-01', 'visible' => true, 'title' => 'Advent of Code 2022 - Nim', 'fragment' => 'aoc2022.md', 'type' => 'aoc', 'cat' => 'blog', 'extras' => ['aoc:year' => '2022'] ], [ 'id' => 28, 'date' => '2022-12-01', 'visible' => true, 'title' => 'Advent of Code 2022 - Nim', 'fragment' => 'aoc2022.md', 'type' => 'aoc', 'cat' => 'blog', 'extras' => ['aoc:year' => '2022'] ],
[ 'id' => 29, 'date' => '2023-09-11', 'visible' => true, 'title' => 'Project Lawful ebook', 'fragment' => 'proj_lawful_ebook.html', 'type' => 'html', 'cat' => 'blog', 'extras' => ['gh_link' => 'https://github.com/Mikescher/ProjectLawfulEbook'] ],
]; ];

View File

@ -0,0 +1,181 @@
<div class="project-lawful-ebook-blogpost">
This is my attempt at creating an ebook version of the <a href="https://www.projectlawful.com/">project lawful</a> story/glowfic.
<ul>
<li>I used the cache file of <a href="https://github.com/QuartzLibrary/glowpub">glowpub</a> as a basis, because I didn't want to write my own scraper (thanks to <a href="https://github.com/QuartzLibrary">github.com/QuartzLibrary</a>)</li>
<li>Then I <a href="https://github.com/Mikescher/ProjectLawfulEbook">hacked together a bit of C# code</a> to generate epub files</li>
<li>All external images (and optionally avatars) are included in the epub</li>
<li>I went through all the avatar files and made them square images (simplified my css, and looked better - most were already squares or almost-squares)</li>
<li>Various properties of the final file/layout can be changed, I generated the variants I found useful, but if anyone wants something special it should be enough to close the repo, edit <code>Program.cs</code> and run <code>make</code></li>
</ul>
<h2># Variants</h2>
I recommend either the <code>project-lawful-inline.epub</code> or the <code>project-lawful-avatars.epub</code> variants
(the <code>*-avatars</code> version contains the post profile-pictures, but is bigger and takes longer to open on older devices).
There are 3 different versions of the actual **content** of the files:
<ul>
<li>the normal one includes all threads from <a href="https://www.projectlawful.com/">projectlawful.com</a>, including sandboxes and lectures. If there is a SFW version of a thread, it is not included (the inline/nsfw is included instead)</li>
<li>the <code>*-sfw-*</code> versions have the NSFW threads replaced wih their SFW counterparts<br/><i>(replaces threads 5310 with 5403, 5610 with 5618, 5638 with 5671)</i></li>
<li>the <code>*-onlymainstory-*</code> versions do not include the sandbox threads or the (optional) lecture threads<br/><i>(removes threads 5775, 5778, 5785, 5826, 5864, 5880, 6029, 6124)</i></li>
</ul>
There are also 5 different layout options (that I code-built) for every version above:
<ul>
<li>the <code>*-inline</code> variant only includes the character-name of each post, and (if possible) the character-name is set inline with the first paragraph</li>
<li>the <code>*-moreinfo</code> variant also includes the alignment text of each post/character after the character-name.</li>
<li>the <code>*-avatars</code> variant show the character avatar beside each post. This forces us to include all 600-ish avatars in the epub file, which increases filesize and loading time</li>
<li>the <code>*-avatars-moreinfo</code> also includes the alignment text (additionally to the avatar). Here the avatar/character-name/alignment-text are also no longer inlined, but get their own paragraph at the start of every post.</li>
<li>the <code>*-biggerhtml</code> variant looks the same as <code>*-inline</code>, but internally every chapter is a single big file (instead of multiple split files), this makes the initial loading of the epub slower, but codevents a forced page-break after every 128th post.</li>
</ul>
As said above, it should be possible to create epub's with other combination of options (see <code>Program.cs</code> and <code>Options.cs</code>)
<h2># Tested on</h2>
<ul>
<li>Kindle Paperwhite /w KOReader</li>
<li>Foliate</li>
<li>epub.js</li>
<li>Calibre Ebook viewer</li>
</ul>
<h2># Download</h2>
<div class="variant">
<h3>project-lawful-inline.epub</h3>
<div class="dlbutton">
<img alt="page preview" src="/data/images/blog/ple-scaled-inline-01.jpeg">
<a rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/inline">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">Download</span>
<span class="span_mb">(30.9 MB)</span>
</a>
</div>
<img alt="page preview" src="/data/images/blog/ple-scaled-inline-01.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-inline-02.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-inline-03.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-inline-04.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-inline-05.jpeg">
</div>
<div class="variant">
<h3>project-lawful-avatars.epub</h3>
<div class="dlbutton">
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-01.jpeg">
<a rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/avatars">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">Download</span>
<span class="span_mb">(37.5 MB)</span>
</a>
</div>
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-01.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-02.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-03.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-04.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-05.jpeg">
</div>
<div class="variant">
<h3>project-lawful-avatars-moreinfo.epub</h3>
<div class="dlbutton">
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-moreinfo-01.jpeg">
<a rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/avatars-moreinfo">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">Download</span>
<span class="span_mb">(37.6 MB)</span>
</a>
</div>
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-moreinfo-01.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-moreinfo-02.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-moreinfo-03.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-moreinfo-04.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-avatars-moreinfo-05.jpeg">
</div>
<div class="variant">
<h3>project-lawful-moreinfo.epub</h3>
<div class="dlbutton">
<img alt="page preview" src="/data/images/blog/ple-scaled-moreinfo-01.jpeg">
<a rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/moreinfo">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">Download</span>
<span class="span_mb">(30.9 MB)</span>
</a>
</div>
<img alt="page preview" src="/data/images/blog/ple-scaled-moreinfo-01.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-moreinfo-02.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-moreinfo-03.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-moreinfo-04.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-moreinfo-05.jpeg">
</div>
<div class="variant">
<h3>project-lawful-biggerhtml.epub</h3>
<div class="dlbutton">
<img alt="page preview" src="/data/images/blog/ple-scaled-biggerhtml-01.jpeg">
<a rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/biggerhtml">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">Download</span>
<span class="span_mb">(30.6 MB)</span>
</a>
</div>
<img alt="page preview" src="/data/images/blog/ple-scaled-biggerhtml-01.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-biggerhtml-02.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-biggerhtml-03.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-biggerhtml-04.jpeg">
<img alt="page preview" src="/data/images/blog/ple-scaled-biggerhtml-05.jpeg">
</div>
<div class="variant alt-variants">
<h3>Alternatives (SFW)</h3>
<a class="dlbtn_alt" rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/sfw-inline">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">project-lawful-sfw-inline</span><span class="span_mb">(30.8 MB)</span>
</a>
<a class="dlbtn_alt" rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/sfw-avatars">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">project-lawful-sfw-avatars</span><span class="span_mb">(37.4 MB)</span>
</a>
<a class="dlbtn_alt" rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/sfw-avatars-moreinfo">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">project-lawful-sfw-avatars-moreinfo</span><span class="span_mb">(37.5 MB)</span>
</a>
<a class="dlbtn_alt" rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/sfw-moreinfo">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">project-lawful-sfw-moreinfo</span><span class="span_mb">(30.8 MB)</span>
</a>
<a class="dlbtn_alt" rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/sfw-biggerhtml">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">project-lawful-sfw-biggerhtml</span><span class="span_mb">(30.5 MB)</span>
</a>
</div>
<div class="variant alt-variants">
<h3>Alternatives (Only-Main-Story)</h3>
<a class="dlbtn_alt" rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/onlymainstory-inline">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">project-lawful-onlymainstory-inline</span><span class="span_mb">(30.5 MB)</span>
</a>
<a class="dlbtn_alt" rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/onlymainstory-avatars">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">project-lawful-onlymainstory-avatars</span><span class="span_mb">(37.2 MB)</span>
</a>
<a class="dlbtn_alt" rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/onlymainstory-avatars-moreinfo">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">project-lawful-onlymainstory-avatars-moreinfo</span><span class="span_mb">(37.3 MB)</span>
</a>
<a class="dlbtn_alt" rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/onlymainstory-moreinfo">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">project-lawful-onlymainstory-moreinfo</span><span class="span_mb">(30.6 MB)</span>
</a>
<a class="dlbtn_alt" rel="nofollow" href="/blog/29/Project_Lawful_ebook/download/onlymainstory-biggerhtml">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><use xlink:href="/data/images/icons.svg#download"/></svg>
<span class="span_dl">project-lawful-onlymainstory-biggerhtml</span><span class="span_mb">(30.2 MB)</span>
</a>
</div>
</div>