Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Рефакторит формирование RSS-ленты подкаста #387

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion eleventy.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export default async function(eleventyConfig) {
templateFormats: [
'md',
'njk',
'11ty.js',
],
};
};
26 changes: 24 additions & 2 deletions src/eleventy-config/filters.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import hyphenLibRu from 'hyphen/ru/index.js';
import markdownIt from 'markdown-it';
import htmlmin from 'html-minifier-terser';
import { stripHeadings, stripLists } from '../libs/markdown-transforms.js';

const markdown = markdownIt({
html: true,
Expand Down Expand Up @@ -61,12 +62,33 @@ export default function(eleventyConfig) {
return markdown.renderInline(value);
});

eleventyConfig.addFilter('htmlmin', (value) => {
return htmlmin.minify(
eleventyConfig.addFilter('htmlmin', async(value) => {
return await htmlmin.minify(
value, {
collapseWhitespace: true,
removeEmptyElements: true,
}
);
});

eleventyConfig.addFilter('duration', (time) => {
// если длительность берётся из json-файла, то она задана в миллисекундах
if (typeof time === 'number') {
return Math.round(time / 1000);
}

return time.split(':').reduceRight((acc, item, index, items) => {
return acc += parseFloat(item) * Math.pow(60, items.length - 1 - index);
}, 0);
});

const podcastMarkdown = markdownIt({
html: true,
})
.use(stripHeadings)
.use(stripLists);

eleventyConfig.addFilter('podcastMarkdown', (content) => {
return podcastMarkdown.render(content);
});
};
62 changes: 62 additions & 0 deletions src/libs/markdown-transforms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
function stripHeadings(md) {
md.core.ruler.push('strip_headings', (state) => {
state.tokens.forEach((token) => {
if (token.type === 'heading_open') {
token.tag = 'p';
token.type = 'paragraph_open';
}

if (token.type === 'heading_close') {
token.tag = 'p';
token.type = 'paragraph_close';
}
});
});
}

function stripLists(md) {
md.core.ruler.push('strip_lists', (state) => {
let newTokens = [];
let isListItemProcessing = false;

state.tokens.forEach((token) => {
if (token.type === 'bullet_list_open') {
const listOpenToken = new state.Token('html_paragraph', 'p', 1);
newTokens.push(listOpenToken);
return;
}

if (token.type === 'bullet_list_close') {
const listCloseToken = new state.Token('html_paragraph', 'p', -1);
newTokens.push(listCloseToken);
return;
}

if (token.type === 'list_item_open') {
isListItemProcessing = true;
return;
}

if (token.type === 'list_item_close') {
isListItemProcessing = false;
return;
}

if (token.type === 'inline' && isListItemProcessing) {
const bulletToken = new state.Token('html_inline', '', 0);
bulletToken.content = '• ';
token.children.unshift(bulletToken);

const breakToken = new state.Token('html_inline', '', 0);
breakToken.content = '<br>';
token.children.push(breakToken);
}

newTokens.push(token);
});

state.tokens = newTokens;
});
}

export { stripHeadings, stripLists };
105 changes: 0 additions & 105 deletions src/pages/podcast/feed.11ty.js

This file was deleted.

75 changes: 75 additions & 0 deletions src/pages/podcast/feed.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
permalink: /podcast/feed/index.xml
---

<?xml version='1.0' encoding='utf-8'?>
<rss
version='2.0'
xmlns:atom='http://www.w3.org/2005/Atom'
xmlns:itunes='http://www.itunes.com/dtds/podcast-1.0.dtd'
xmlns:content='http://purl.org/rss/1.0/modules/content/'
>
<channel>
<title>{{podcast.title}}</title>
<description><![CDATA[{{podcast.description | inlineMarkdown | safe}}]]></description>
<copyright>{{podcast.copyright}}</copyright>
<language>{{podcast.language}}</language>
<link>{{podcast.url}}</link>

<atom:link href='{{podcast.url}}feed/' rel='self' type='application/rss+xml'/>

<itunes:subtitle>{{podcast.subtitle}}</itunes:subtitle>
<itunes:type>{{podcast.type}}</itunes:type>
<itunes:author>{{podcast.author}}</itunes:author>
<itunes:explicit>{{podcast.explicit}}</itunes:explicit>
<itunes:owner>
<itunes:name>{{podcast.owner.name}}</itunes:name>
<itunes:email>{{podcast.owner.email}}</itunes:email>
</itunes:owner>
<itunes:image href='{{podcast.url}}cover.png'/>

{% for category in podcast.categories %}
<itunes:category text='{{category.title}}'>
{% for categoryItem in category.items %}
<itunes:category text='{{categoryItem}}'/>
{% endfor %}
</itunes:category>
{% endfor %}

{% for episode in collections.episodes | reverse %}
{% set hosts = episode.data.hosts | join(', ') %}
<item>
<title>{{episode.fileSlug}}. {{episode.data.title}}</title>
<link>{{podcast.url}}{{episode.fileSlug}}/</link>
<pubDate>{{episode.date.toUTCString()}}</pubDate>
{% set hostsAndChaptersBlock %}
<p>Ведущие: {{hosts}}</p>
{% if episode.data.chapters.length > 0 %}
<p>Темы</p>
<p>
{% for chapter in episode.data.chapters %}
{{chapter.time}} {{chapter.title}}{% if not loop.last %}<br>{% endif %}
{% endfor %}
</p>
{% endif %}
{% endset %}
<description><![CDATA[
{{hostsAndChaptersBlock | safe}}
{{episode.rawInput | podcastMarkdown | htmlmin | safe }}
]]></description>
<guid isPermaLink='true'>{{podcast.url}}episodes/{{episode.fileSlug}}.mp3</guid>
<enclosure
type='audio/mpeg'
url='{{podcast.url}}episodes/{{episode.fileSlug}}.mp3'
length='{{episode.data.fileSize}}'
/>
<itunes:episode>{{episode.fileSlug}}</itunes:episode>
<itunes:duration>{{episode.data.duration | duration}}</itunes:duration>
<itunes:author>{{hosts}}</itunes:author>
<itunes:explicit>{{podcast.explicit}}</itunes:explicit>
<itunes:summary>{{episode.date | ruDate}}: {{episode.data.title}}. {{hosts}}</itunes:summary>
<itunes:image href='{{podcast.url}}cover.png'/>
</item>
{% endfor %}
</channel>
</rss>
Loading