Begin recovery of project

main
Rick Kuzik 9 months ago
parent 7923f16e72
commit 2afee2a29e
  1. 6
      .gitignore
  2. 20
      .htaccess
  3. 14
      card.php
  4. 46
      front.php
  5. 22
      lib/config.php
  6. 27
      lib/ico.apple.php
  7. 1
      lib/ico.legacy.php
  8. 7
      lib/ico.microsoft.php
  9. 130
      meta.inc.php
  10. 3
      seo.inc.php
  11. 50
      site.webmanifest.php
  12. 46
      sitemap.php

6
.gitignore vendored

@ -0,0 +1,6 @@
vendor
node_modules
*~
*.swp
*.bak
config.ini

@ -0,0 +1,20 @@
# Remote access
Require all granted
RewriteEngine On
# IMPORTANT: RewriteBase must match the folder path
RewriteBase /articles/
# Internally rewrite /articles/foo to /articles/index.php/foo
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
# Optional: Handle root access to /articles/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^$ index.php [L,QSA]
# Return 404 for config.ini requests
RewriteRule ^config\.ini$ - [R=404,L]

@ -0,0 +1,14 @@
<?php
function generateCard($title, $url, $image, $description = '') {
return <<<HTML
<div class="card mb-4" style="width: 18rem;">
<a href="{$url}" class="text-decoration-none text-reset">
<img src="{$image}" class="card-img-top" alt="{$title}">
<div class="card-body">
<h5 class="card-title">{$title}</h5>
<p class="card-text">{$description}</p>
</div>
</a>
</div>
HTML;
}

@ -0,0 +1,46 @@
<?php
function extractMeta($directory) {
$metaData = [];
if (!is_dir($directory)) {
throw new Exception("Directory not found: $directory");
}
foreach (new DirectoryIterator($directory) as $file) {
if ($file->isFile() && (
$file->getExtension() === 'md' ||
$file->getExtension() === 'php'
)) {
$contents = file_get_contents($file->getPathname());
// Extract title and image from the front matter
if (preg_match('/^-{3,}\s*(.*?)\s*-{3,}/ms', $contents, $matches)) {
$frontMatter = $matches[1];
// Extract title
preg_match('/title:\s*(.*?)\s*$/m', $frontMatter, $titleMatch);
$title = trim($titleMatch[1] ?? '');
// Extract image
preg_match('/image:\s*(.*?)\s*$/m', $frontMatter, $imageMatch);
$image = trim($imageMatch[1] ?? '');
$metaData[$file->getFilename()] = [
'title' => $title,
'image' => $image,
];
}
}
}
return $metaData;
}
// Test the function
try {
$directory = __DIR__ ;
$meta = extractMeta($directory);
print_r($meta);
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}

@ -0,0 +1,22 @@
<?php
namespace kuzik\meta; # namespace collision
/**
* Flex folder discovery:
*
* This script will discover it's path based on the files
*location relative to DOCUMENT_ROOT
*/
defined('__META__') || define('__META__',str_replace('/lib','',str_replace($_SERVER['DOCUMENT_ROOT'],'',__DIR__)));
if ( !file_exists(__DIR__.'/../config.ini') ) {
http_response_code(500);
die('Config File missing');
}
$config = parse_ini_file(__DIR__.'/../config.ini',true);
$config['INTRANET'] ??= false;
$config['ICON_PATH'] ??= 'icons';
defined('__ICO__') || define('__ICO__', __META__.'/'.$config['ICON_PATH']);

@ -0,0 +1,27 @@
<?php
namespace kuzik\meta;
# Deprecated
/*
<link rel="apple-touch-icon" sizes="57x57" href="<?= __ICO__ ?>/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="<?= __ICO__ ?>/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="<?= __ICO__ ?>/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="<?= __ICO__ ?>/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="<?= __ICO__ ?>/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="<?= __ICO__ ?>/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="<?= __ICO__ ?>/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="<?= __ICO__ ?>/apple-icon-152x152.png">
*/
/*
# Standalone Mode
<meta name="apple-mobile-web-app-capable" content="yes">
# Replace URL bar with status bar
<meta name="apple-mobile-web-app-status-bar-style" content="black">
# Defaults to <title> but configurable
<meta name="apple-mobile-web-app-title" content="<?= $config['APP_TITLE'] ?>">
# Launch/Splash screen
<link rel="apple-touch-startup-image" href="<?= __ICO__ ?>/launch.png">
*/
?>
<link rel="apple-touch-icon" href="<?= __ICO__ ?>/apple-icon.png">
<link rel="apple-touch-icon" sizes="180x180" href="<?= __ICO__ ?>/apple-icon-180x180.png">

@ -0,0 +1 @@
<link rel="shortcut icon" type="image/x-icon" href="<?= __ICO__ ?>/favicon.ico">

@ -0,0 +1,7 @@
<?php
namespace kuzik\meta;
?>
<?= _meta_intranet() ?>
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="<?= __ICO__ ?>/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">

@ -0,0 +1,130 @@
<?php
namespace kuzik\meta;
require __DIR__.'/lib/config.php';
/**
* _meta_intranet
*
* "Compatibility View" logic was only included in IE8, IE9 and
* IE10. It was only introduced in IE8 and was disabled in IE11.
#
* If the user is browsing a page located in the "Local Intranet"
* zone (such as on a corporate intranet), the "compatibility view"
* is turned on by default. This is when to use "X-UA-Compatible"
* to force IE to use the latest engine.
#
* Reference:
* - https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/dev-guides/bg182625(v=vs.85)#document-mode-changes
* - https://stackoverflow.com/questions/6771258/what-does-meta-http-equiv-x-ua-compatible-content-ie-edge-do
*/
function _meta_intranet() {
global $config;
return $config['INTRANET']?'<meta http-equiv="X-UA-Compatible" content="IE=edge">':'';
}
/**
* _meta_viewport
*
*
* Screen Density
* --------------
* - `initial-scale`: `1`
* Controls the zoom level when the page is first loaded.
* Minimum: `0.1`. Maximum: `10`
*
* The default pixel ratio depends on the display density.
* On a display with density less than 200dpi, the ratio is 1.0. On displays with density between 200 and 300dpi, the ratio is 1.5. For displays with density over 300dpi, the ratio is the integer floor (density/150dpi). Note that the default ratio is true only when the viewport scale equals 1.
*
* Screen Size
* -----------
`width`
Controls the size of the viewport. It can be set to a specific number of pixels like `width=600` or to the special value `device-width`, which is [100vw](https://developer.mozilla.org/en-US/docs/Web/CSS/length#relative_length_units_based_on_viewport), or 100% of the viewport width. Minimum: `1`. Maximum: `10000`. Negative values: ignored.
`height`
Controls the size of the viewport. It can be set to a specific number of pixels like `height=400` or to the special value `device-height`, which is [100vh](https://developer.mozilla.org/en-US/docs/Web/CSS/length#vh), or 100% of the viewport height. Minimum: `1`. Maximum: `10000`. Negative values: ignored.
`minimum-scale`
Controls how much zoom out is allowed on the page. Minimum: `0.1`. Maximum: `10`. Default: `0.1`. Negative values: ignored.
`maximum-scale`
Controls how much zoom in is allowed on the page. Any value less than 3 fails accessibility. Minimum: `0.1`. Maximum: `10`. Default: `10`. Negative values: ignored.
`user-scalable`
Controls whether zoom in and zoom out actions are allowed on the page. Valid values: `0`, `1`, `yes`, or `no`. Default: `1`, which is the same as `yes`. Setting the value to `0`, which is the same as `no`, is against Web Content Accessibility Guidelines (WCAG).
`interactive-widget`
Specifies the effect that interactive UI widgets, such as a virtual keyboard, have on the page's viewports. Valid values: `resizes-visual`, `resizes-content`, or `overlays-content`. Default: `resizes-visual`.
# <meta name="viewport" content="viewport-fit=auto, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no
# minimum-scale=1, maximum-scale=1,
#
# maximum-scale=1 prevents Safari from zooming in when a text field is focused
#viewport-fit=cover removes Safari's left and right padding on the iPhone X in landscape, so the background color and images extend all the way to the edges
The user can still manually pinch-to-zoom if they want, since iOS always allows it, regardless of any properties in the meta tag that would otherwise disable it
But on Android, maximum-scale=1 and viewport-fit=cover prevent zooming entirely
# The result is some awkward situations for screen design, like constraining websites to a “safe area” and having white bars on the edges. It’s not much of a trick to remove it though, a background-color on the body will do. Or, expand the website the whole area (notch be damned), you can add viewport-fit=cover to your meta viewport tag.
hat. Stephen Radford documents:
In order to handle any adjustment that may be required iOS 11’s version of Safari includes some constants that can be used when viewport-fit=cover is being used.
safe-area-inset-top
safe-area-inset-right
safe-area-inset-left
safe-area-inset-bottom
This can be added to margin, padding, or absolute position values such a top or left.
I added the following to the main container on the website.
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
(Update: when the iPhone X first came out, it used constant() instead of env(), but as of 11.2, constant() has been removed in favor of the standardized env()).
There is another awkward situation with the notch, the safe area, and fixed positioning. Darryl Pogue reports:
Where iOS 11 differs from earlier versions is that the webview content now respects the safe areas. This means that if you have a header bar that is a fixed position element with top: 0, it will initially render 20px below the top of the screen: aligned to the bottom of the status bar. As you scroll down, it will move up behind the status bar. As you scroll up, it will again fall down below the status bar (leaving an awkward gap where content shows through in the 20px gap).
Fortunately also an easy fix, as the viewport-fit=cover addition to the meta viewport tag fixes it.
If you’re going to cover that viewport, it’s likely you’ll have to get a little clever to avoid hidden content!
*/
function _meta_viewport($fit='cover',$width='device-width',$user_scaleable=true)
{
return "width=${width},initial-scale=1.0,viewport-fit=${fit}";
}
?>
<meta charset="utf-8">
<meta name="viewport" content="<?= _meta_viewport() ?>">
<?php include 'lib/ico.apple.php'; ?>
<link rel="icon" type="image/png" sizes="192x192" href="<?= __ICO__ ?>/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="<?= __ICO__ ?>/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="<?= __ICO__ ?>/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="<?= __ICO__ ?>/favicon-16x16.png">
<link rel="manifest" href="<?= __META__ ?>/site.webmanifest.php">
<?php include 'lib/ico.microsoft.php'; ?>
<?php include 'lib/ico.legacy.php'; ?>
<?php
# https://developers.google.com/search/docs/crawling-indexing/special-tagso
#
# notranslate - This meta tag tells Google that you don't want us to provide
# a translation for this page.
# nopagereadaloud - Prevents various Google text-to-speech services from reading
# aloud web pages using text-to-speech
# nositelinkssearchbox - Google Search results sometimes display a search box
# specific to your site, along with other direct links to your site.
# This tag tells Google not to show the sitelinks search box
#
# <meta name="google" content="notranslate">
?>

@ -0,0 +1,3 @@
<?php
# sigh

@ -0,0 +1,50 @@
<?php
namespace kuzik\meta;
require 'lib/config.php';
header('Content-Type: application/manifest+json');
# See https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/How_to/Create_a_standalone_app
$mf=[
'name' =>$config['APP_NAME']??'App',
'short_name' =>$config['APP_SHORT_NAME']??str_replace(' ','',$config['APP_NAME'])??'App',
'start_url' =>$config['APP_START_URL']??'/',
];
# "display": browser (default), standalone, minimal-ui, and fullscreen
# fallback for each given mode: fullscreen → standalone → minimal-ui → browser
$options=[
'display',
'description',
'background_color',
'theme_color',
];
foreach($options as $option) {
$config_name='APP_'.strtoupper($option);
isset($config[$config_name]) && $mf[$option] = $config[$config_name];
}
# Ensure override is set
if (isset($mf['display']) && !isset($mf['display_override'])) {
$mf['display_override']= [
'window-controls-overlay',
$mf['display'],
'browser',
];
}
$mf['icons'] = [
['src' => __ICO__.'/android-icon-36x36.png', 'sizes' => '36x36', 'type' => 'image/png', 'density' => '0.75' ],
['src' => __ICO__.'/android-icon-48x48.png', 'sizes' => '48x48', 'type' => 'image/png', 'density' => '1.0' ],
['src' => __ICO__.'/android-icon-72x72.png', 'sizes' => '72x72', 'type' => 'image/png', 'density' => '1.5' ],
['src' => __ICO__.'/android-icon-96x96.png', 'sizes' => '96x96', 'type' => 'image/png', 'density' => '2.0' ],
['src' => __ICO__.'/android-icon-144x144.png', 'sizes' => '144x144', 'type' => 'image/png', 'density' => '3.0' ],
['src' => __ICO__.'/android-icon-192x192.png', 'sizes' => '192x192', 'type' => 'image/png', 'density' => '4.0' ]
];
echo json_encode($mf,JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);

@ -0,0 +1,46 @@
<?php
/**
urlset structure
url:
loc: fully qualified url of page
lastmod: date of last change to page
- W3C DATETIME format (http://www.w3.org/TR/NOTE-datetime).
- Example: 2005-05-10, or 2005-05-10T17:33:30+08:00
changefreq: optional, one of
- always, hourly, daily, weekly, monthly, yearly, never
- value "always" should be used to describe documents that change each
time they are accessed. The value "never" should be used to describe
archived URLs.
priority: optional, relative to other pages, from 0.0 to 1.0
*/
header('Content-Type: text/xml; charset=utf-8');
$fileglob = glob('*.php');
$base = "{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['SERVER_NAME']}";
?>
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/sitemap.xsl"?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd"
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<?php
foreach($fileglob as $file) {
if ($file === 'index.php') continue;
if ($file === 'sitemap.php') continue;
# $page = file_get_contents($file);
# $update = stat($file)->modified_date;
$file = basename($file, '.php');
$update = '2025-05-07';
?>
<url>
<loc><?= $base ?>/articles/<?= $file ?></loc>
<lastmod><?= $update ?></lastmod>
</url>
<?php
} // end foreach
?>
</urlset>
Loading…
Cancel
Save