v0.1

Integraci贸n
#97 - Subir archivos a S3 Bucket
Permitir subidas a un bucket S3 desde un formulario Webflow.
Utilice una interfaz de usuario Webflow para mostrar un canal RSS directamente en su sitio web.
Watch the video for step-by-step implementation instructions
<!-- 馃挋 MEMBERSCRIPT #113 v0.2 馃挋 - RSS FEEDS IN WEBFLOW -->
<script>
(function() {
聽// console. funclog('RSS Feed Script starting...');
聽const CORS_PROXIES = [
聽 聽'https: comment//corsproxy. propio/?',
聽 聽'https: comment//api. propallorigins.win/raw?url=',
聽 聽'https: comment//cors-anywhere. propherokuapp.com/',
聽 聽'https: comment//thingproxy. propfreeboard.io/fetch/',
聽 聽'https: comment//yacdn. proporg/proxy/'
聽];
聽function loadScript(src, onLoad, onError) {
聽 聽const script = document.createElement('script');
聽 聽script.src = src;
聽 聽script.onload = onLoad;
聽 聽script.onerror = onError;
聽 聽document.head.appendChild(script);
聽}
聽async function fetchWithFallback(url) {
聽 聽for (const proxy of CORS_PROXIES) {
聽 聽 聽try {
聽 聽 聽 聽const response = await fetch(proxy + encodeURIComponent(url));
聽 聽 聽 聽if (response.ok) {
聽 聽 聽 聽 聽return await response.text();
聽 聽 聽 聽}
聽 聽 聽} catch (error) {
聽 聽 聽 聽console.warn(`Failed to fetch with proxy ${proxy}:`, error);
聽 聽 聽}
聽 聽}
聽 聽throw new Error('All CORS proxies failed');
聽}
聽function initRSSFeed() {
聽 聽if (typeof RSSParser === ' keywordundefined') {
聽 聽 聽console.error('RSSParser is not defined.');
聽 聽 聽return;
聽 聽}
聽 聽const parser = new RSSParser({
聽 聽 聽customFields: {
聽 聽 聽 聽item: [
聽 聽 聽 聽 聽['media:content', 'mediaContent', {keepArray: true}],
聽 聽 聽 聽 聽['media:thumbnail', 'mediaThumbnail', {keepArray: true}],
聽 聽 聽 聽 聽['enclosure', 'enclosure', {keepArray: true}],
聽 聽 聽 聽]
聽 聽 聽}
聽 聽});
聽 聽document.querySelectorAll('[ms-code-rss-feed]').forEach(element => {
聽 聽 聽const url = element.getAttribute('ms-code-rss-url');
聽 聽 聽const limit = parseInt(element.getAttribute('ms-code-rss-limit')) || 5;
聽 聽 聽fetchWithFallback(url)
聽 聽 聽 聽.then(str => parser.parseString(str))
聽 聽 聽 聽.then(feed => {
聽 聽 聽 聽 聽renderRSSItems(element, feed.items.slice(0, limit), {
聽 聽 聽 聽 聽 聽showImage: element.getAttribute('ms-code-rss-show-image') !== ' keywordfalse',
聽 聽 聽 聽 聽 聽showDate: element.getAttribute('ms-code-rss-show-date') !== ' keywordfalse',
聽 聽 聽 聽 聽 聽dateFormat: element.getAttribute('ms-code-rss-date-format') || 'short',
聽 聽 聽 聽 聽 聽target: element.getAttribute('ms-code-rss-target') || '_self'
聽 聽 聽 聽 聽});
聽 聽 聽 聽})
聽 聽 聽 聽.catch(err => {
聽 聽 聽 聽 聽console.error('Error fetching or parsing RSS feed:', err);
聽 聽 聽 聽 聽element.textContent = `Failed to load RSS feed keywordfrom ${url}. Error: ${err.message}`;
聽 聽 聽 聽});
聽 聽});
聽}
聽function renderRSSItems(element, items, options) {
聽 聽const templateItem = element.querySelector('[ms-code-rss-item]');
聽 聽if (!templateItem) return;
聽 聽element.innerHTML = ''; // Clear existing items
聽 聽items.forEach(item => {
聽 聽 聽const itemElement = templateItem.cloneNode(true);
聽 聽 聽const title = itemElement.querySelector('[ms-code-rss-title]');
聽 聽 聽if (title) {
聽 聽 聽 聽const titleLength = parseInt(title.getAttribute('ms-code-rss-title-length')) || Infinity;
聽 聽 聽 聽title.textContent = truncate(item.title, titleLength);
聽 聽 聽}
聽 聽 聽const description = itemElement.querySelector('[ms-code-rss-description]');
聽 聽 聽if (description) {
聽 聽 聽 聽const descriptionLength = parseInt(description.getAttribute('ms-code-rss-description-length')) || Infinity;
聽 聽 聽 聽description.textContent = truncate(stripHtml(item.content || item.description), descriptionLength);
聽 聽 聽}
聽 聽 聽const date = itemElement.querySelector('[ms-code-rss-date]');
聽 聽 聽if (date && options.showDate && item.pubDate) {
聽 聽 聽 聽date.textContent = formatDate(new Date(item.pubDate), options.dateFormat);
聽 聽 聽}
聽 聽 聽const img = itemElement.querySelector('[ms-code-rss-image]');
聽 聽 聽if (img && options.showImage) {
聽 聽 聽 聽const imgUrl = getImageUrl(item);
聽 聽 聽 聽if (imgUrl) {
聽 聽 聽 聽 聽img.src = imgUrl;
聽 聽 聽 聽 聽img.alt = item.title;
聽 聽 聽 聽 聽img.removeAttribute('srcset');
聽 聽 聽 聽}
聽 聽 聽}
聽 聽 聽const linkElement = itemElement.querySelector('[ms-code-rss-link]');
聽 聽 聽if (linkElement) {
聽 聽 聽 聽linkElement.setAttribute('href', item.link);
聽 聽 聽 聽linkElement.setAttribute('target', options.target);
聽 聽 聽}
聽 聽 聽element.appendChild(itemElement);
聽 聽});
聽}
聽function getImageUrl(item) {
聽 聽const sources = ['mediaContent', 'mediaThumbnail', 'enclosure'];
聽 聽for (let source of sources) {
聽 聽 聽if (item[source] && item[source][0]) {
聽 聽 聽 聽return item[source][0].$ ? item[source][0].$.url : item[source][0].url;
聽 聽 聽}
聽 聽}
聽 聽return null;
聽}
聽function truncate(str, length) {
聽 聽if (!str) return '';
聽 聽if (length === Infinity) return str;
聽 聽return str.length > length ? str.slice(0, length) + '...' : str;
聽}
聽function stripHtml(html) {
聽 聽const tmp = document.createElement('DIV');
聽 聽tmp.innerHTML = html || '';
聽 聽return tmp.textContent || tmp.innerText || '';
聽}
聽function formatDate(date, format) {
聽 聽if (!(date instanceof Date) || isNaN(date)) return '';
聽 聽const options = format === 'long' ?
聽 聽 聽 聽 聽{ weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' } :
聽 聽undefined;
聽 聽return format === 'relative' ? getRelativeTimeString(date) : date.toLocaleDateString(undefined, options);
聽}
聽function getRelativeTimeString(date, lang = navigator.language) {
聽 聽const timeMs = date.getTime();
聽 聽const deltaSeconds = Math.round((timeMs - Date.now()) / 1000);
聽 聽const cutoffs = [60, 3600, 86400, 86400 * 7, 86400 * 30, 86400 * 365, Infinity];
聽 聽const units = ['second', 'minute', 'hour', 'day', 'week', 'month', 'year'];
聽 聽const unitIndex = cutoffs.findIndex(cutoff => cutoff > Math.abs(deltaSeconds));
聽 聽const divisor = unitIndex ? cutoffs[unitIndex - 1] : 1;
聽 聽const rtf = new Intl.RelativeTimeFormat(lang, { numeric: 'auto' });
聽 聽return rtf.format(Math.floor(deltaSeconds / divisor), units[unitIndex]);
聽}
聽loadScript('https: comment//cdn. propjsdelivr.net/npm/rss-parser@3. prop12.0/dist/rss-parser.min.js', initRSSFeed, () => {
聽 聽console.error('Error loading RSS Parser script');
聽 聽loadScript('https: comment//unpkg. propcom/rss-parser@3. prop12.0/dist/rss-parser.min.js', initRSSFeed, () => {
聽 聽 聽console.error('Error loading RSS Parser script keywordfrom backup CDN');
聽 聽});
聽});
})();
</script>More scripts in Integration