` in the head (AgentReady
* AR-READ-09) and the matching Link header. The href is the page's own URL —
* the same URL serves markdown on `Accept: text/markdown`.
*
* @return void
*/
function output_markdown_alternate_link(): void {
if ( ! is_feature_enabled( 'markdown' ) || is_admin() || is_feed() || is_404() ) {
return;
}
$url = markdown_alternate_url();
if ( '' === $url ) {
return;
}
echo '' . "\n";
}
/**
* URL of the current view for the alternate link ('' when unknown).
*
* @return string
*/
function markdown_alternate_url(): string {
if ( is_front_page() ) {
return home_url( '/' );
}
if ( is_singular() ) {
$permalink = get_permalink();
return is_string( $permalink ) ? $permalink : '';
}
global $wp;
if ( $wp instanceof \WP && is_string( $wp->request ) ) {
return home_url( user_trailingslashit( $wp->request ) );
}
return '';
}
/**
* YAML frontmatter block for the markdown representation: title, URL, site,
* modification date, and the HTTP status for error pages. Lets an agent
* identify what it fetched without parsing the body.
*
* @return string
*/
function markdown_frontmatter(): string {
$yaml = static function ( string $value ): string {
return '"' . str_replace( array( '\\', '"' ), array( '\\\\', '\\"' ), markdown_safe_text( $value ) ) . '"';
};
$lines = array( '---' );
$lines[] = 'title: ' . $yaml( is_404() ? __( 'Not found', 'aj-agent-crawl-optimizer' ) : wp_get_document_title() );
$url = markdown_alternate_url();
if ( '' !== $url ) {
$lines[] = 'url: ' . esc_url_raw( $url );
}
$lines[] = 'site: ' . $yaml( get_bloginfo( 'name' ) );
if ( is_singular() ) {
$modified = get_post_modified_time( 'c', true );
if ( is_string( $modified ) ) {
$lines[] = 'modified: ' . $modified;
}
}
if ( is_404() ) {
$lines[] = 'status: 404';
}
$lines[] = '---';
return implode( "\n", $lines ) . "\n\n";
}
/**
* Check if the current request accepts Markdown.
*
* @return bool
*/
function accepts_markdown(): bool {
if ( ! isset( $_SERVER['HTTP_ACCEPT'] ) ) {
return false;
}
$accept = sanitize_text_field( wp_unslash( $_SERVER['HTTP_ACCEPT'] ) );
// strpos, not str_contains — the WP polyfill only exists since WP 5.9 and
// this plugin supports 5.5+.
return strpos( $accept, 'text/markdown' ) !== false;
}
/**
* Emit `Vary: Accept` on every frontend response while markdown negotiation
* is enabled — the representation varies on the Accept header, so caches and
* CDNs must key on it. Without this, a page cache either serves cached HTML
* to agents (breaking negotiation) or caches the markdown variant for humans.
*
* @return void
*/
function send_markdown_vary_header(): void {
if ( ! is_feature_enabled( 'markdown' ) ) {
return;
}
if ( is_admin() ) {
return;
}
header( 'Vary: Accept', false );
if ( ! is_feed() && ! is_404() ) {
$url = markdown_alternate_url();
if ( '' !== $url ) {
header( 'Link: <' . esc_url_raw( $url ) . '>; rel="alternate"; type="text/markdown"', false );
}
}
}
/**
* Convert HTML to Markdown.
*
* @param string $html HTML string.
* @return string
*/
function html_to_markdown( string $html ): string {
$markdown = $html;
// Remove script, style, noscript, and comments.
$markdown = preg_replace( '/