Full project: Svelte 5 frontend, Vite 7 backend API, Pug email templates (email-gen), Docker deployment. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
324 lines
17 KiB
Plaintext
324 lines
17 KiB
Plaintext
// Reaspekt master shared factory mixins
|
||
|
||
mixin ctaButtonSection(opts = {})
|
||
- const width = opts.width || 560
|
||
- const text = opts.text || '#ТЕКСТ#'
|
||
- const href = opts.href || '#ССЫЛКА#'
|
||
- const buttonBg = opts.buttonBg || '#ffffff'
|
||
- const buttonText = opts.buttonText || '#130F33'
|
||
- const iconSrc = opts.iconSrc || 'https://574922.selcdn.ru/email.static/reaspekt/2024_newsletters/2024_09_29/icon-watch-white.png'
|
||
|
||
if width === 560
|
||
tr
|
||
td.padding-wrapper
|
||
+buttonRounded(text, href, 560, 60, buttonBg, 16, buttonText, 0, '', iconSrc, 20, 17, 1, 'right').textVerdana
|
||
else if width === 270
|
||
tr
|
||
td.padding-wrapper
|
||
+defaultTable('560')
|
||
tr
|
||
td(width='270')
|
||
+buttonRounded(text, href, 270, 60, buttonBg, 16, buttonText, 0, '', iconSrc, 20, 17, 1, 'right').textVerdana
|
||
+tdFixed(20)
|
||
td(width='270')
|
||
+buttonRounded(text, href, 270, 60, buttonBg, 16, buttonText, 0, '', iconSrc, 20, 17, 1, 'right').textVerdana
|
||
else if width === 173
|
||
tr
|
||
td.padding-wrapper
|
||
+defaultTable('560')
|
||
tr
|
||
td(width='173')
|
||
+buttonRounded(text, href, 173, 60, buttonBg, 16, buttonText, 0, '', iconSrc, 20, 17, 1, 'right').textVerdana
|
||
+tdFixed(21)
|
||
td(width='173')
|
||
+buttonRounded(text, href, 173, 60, buttonBg, 16, buttonText, 0, '', iconSrc, 20, 17, 1, 'right').textVerdana
|
||
+tdFixed(20)
|
||
td(width='173')
|
||
+buttonRounded(text, href, 173, 60, buttonBg, 16, buttonText, 0, '', iconSrc, 20, 17, 1, 'right').textVerdana
|
||
|
||
mixin ctaLinkSection(opts = {})
|
||
- const width = opts.width || 560
|
||
- const href = opts.href || ''
|
||
- const linkText = opts.linkText || (width === 173 ? 'Любой текст' : 'Как не терять наши письма?')
|
||
- const colorClass = opts.colorClass || 'color__blue'
|
||
- const linkClass = opts.linkClass || 'text__link-blue'
|
||
- const linkColorClass = opts.linkColorClass || textClass
|
||
- const tableWidth = opts.tableWidth || '560'
|
||
|
||
if width === 560
|
||
tr
|
||
td(align='center').padding-wrapper
|
||
a(href=href target='_blank').textVerdana(class=`${colorClass} text__link ${linkClass}`)= linkText
|
||
else if width === 270
|
||
tr
|
||
td.padding-wrapper
|
||
+defaultTable(tableWidth)
|
||
tr
|
||
td(width='270' align='center')
|
||
a(href=href target='_blank').textVerdana(class=`${colorClass} text__link ${linkClass}`)= linkText
|
||
+tdFixed(20)
|
||
td(width='270' align='center')
|
||
a(href=href target='_blank').textVerdana(class=`${colorClass} text__link ${linkClass}`)= linkText
|
||
else if width === 173
|
||
tr
|
||
td.padding-wrapper
|
||
+defaultTable(tableWidth)
|
||
tr
|
||
td(width='173' align='center')
|
||
a(href=href target='_blank').textVerdana(class=`${colorClass} text__link ${linkClass}`)= linkText
|
||
+tdFixed(21)
|
||
td(width='173' align='center')
|
||
a(href=href target='_blank').textVerdana(class=`${colorClass} text__link ${linkClass}`)= linkText
|
||
+tdFixed(20)
|
||
td(width='173' align='center')
|
||
a(href=href target='_blank').textVerdana(class=`${colorClass} text__link ${linkClass}`)= linkText
|
||
|
||
mixin contentCardInner(opts = {})
|
||
- const width = opts.width || 560
|
||
- const titleClass = opts.titleClass || 'color__blue'
|
||
- const textClass = opts.textClass || 'color__blue'
|
||
- const titleSizeClass = opts.titleSizeClass || 'header__h1'
|
||
- const title = opts.title || 'Контекстная реклама для увеличения продаж'
|
||
- const text = opts.text || 'Наша команда стала активнее участвовать в образовательных мероприятиях, на которых мы делимся тонкостями своей работы и рассказываем о практическом опыте. Решили поделиться с вами записями прошедших вебинаров. Вот сводка тем:'
|
||
- const buttonBg = opts.buttonBg || '#ffffff'
|
||
- const buttonText = opts.buttonText || '#130F33'
|
||
- const withImage = !!opts.withImage
|
||
- const imageSrc = opts.imageSrc || 'https://574922.selcdn.ru/email.static/reaspekt/master-tamplate/banners/banner-50-percent.jpg'
|
||
|
||
+defaultTable(`${width}`)
|
||
if withImage
|
||
tr
|
||
td
|
||
+backgroundImageBlock(imageSrc, width, 180, '#ffffff', 'left', 'top')
|
||
+spacerLine(20)
|
||
tr
|
||
td
|
||
span.textVerdana(class=`${titleSizeClass} ${titleClass}`)= title
|
||
+spacerLine(20)
|
||
if opts.firstColumnExtraGap
|
||
+spacerLine(20)
|
||
tr
|
||
td
|
||
span.textVerdana.text__normal(class=textClass)= text
|
||
+spacerLine(20)
|
||
tr
|
||
td
|
||
+buttonRounded('#ТЕКСТ#', '#ССЫЛКА#', width, 60, buttonBg, 16, buttonText, 0, '').textVerdana
|
||
|
||
mixin textSection560(opts = {})
|
||
tr
|
||
td.padding-wrapper(class=opts.bgClass || 'background__white')
|
||
+defaultTable('560')
|
||
+spacerLine(40)
|
||
tr
|
||
td
|
||
span.textVerdana.header__h1(class=opts.titleClass || 'color__blue') Мы продолжаем делать вебинары для вас, а чтобы следить за актуальными темами, подписывайтесь на наше сообщество ВКонтакте
|
||
+spacerLine(20)
|
||
tr
|
||
td
|
||
span.textVerdana.text__normal(class=opts.textClass || 'color__blue') Наша команда стала активнее участвовать в образовательных мероприятиях, на которых мы делимся тонкостями своей работы и рассказываем о практическом опыте. Решили поделиться с вами записями прошедших вебинаров. Вот сводка тем:
|
||
+spacerLine(20)
|
||
tr
|
||
td
|
||
+buttonRounded('#ТЕКСТ#', '#ССЫЛКА#', 560, 60, opts.buttonBg || '#ffffff', 16, opts.buttonText || '#130F33', 0, '').textVerdana
|
||
+spacerLine(40)
|
||
|
||
mixin textSection270(opts = {})
|
||
tr
|
||
td.padding-wrapper(class=opts.bgClass || 'background__white')
|
||
+defaultTable('560')
|
||
+spacerLine(40, 3)
|
||
tr
|
||
td(valign='top')
|
||
+contentCardInner({
|
||
width: 270,
|
||
withImage: true,
|
||
titleClass: opts.titleClass,
|
||
textClass: opts.textClass,
|
||
buttonBg: opts.buttonBg,
|
||
buttonText: opts.buttonText
|
||
})
|
||
+tdFixed(20)
|
||
td(valign='top')
|
||
+contentCardInner({
|
||
width: 270,
|
||
withImage: true,
|
||
titleClass: opts.titleClass,
|
||
textClass: opts.textClass,
|
||
buttonBg: opts.buttonBg,
|
||
buttonText: opts.buttonText
|
||
})
|
||
+spacerLine(40, 3)
|
||
|
||
mixin textSection173(opts = {})
|
||
tr
|
||
td.padding-wrapper(class=opts.bgClass || 'background__white')
|
||
+defaultTable('560')
|
||
+spacerLine(40, 5)
|
||
|
||
mixin textImageSection560(opts = {})
|
||
- const title = opts.title || 'Мы продолжаем делать вебинары для вас, а чтобы следить за актуальными темами, подписывайтесь на наше сообщество ВКонтакте'
|
||
- const text = opts.text || 'Наша команда стала активнее участвовать в образовательных мероприятиях, на которых мы делимся тонкостями своей работы и рассказываем о практическом опыте. Решили поделиться с вами записями прошедших вебинаров. Вот сводка тем:'
|
||
- const imageSrc = opts.imageSrc || 'https://574922.selcdn.ru/email.static/reaspekt/master-tamplate/banners/image.jpg'
|
||
- const bgClass = opts.bgClass || 'background__white'
|
||
- const titleClass = opts.titleClass || 'color__blue'
|
||
- const textClass = opts.textClass || 'color__blue'
|
||
- const buttonBg = opts.buttonBg || '#ffffff'
|
||
- const buttonText = opts.buttonText || '#130F33'
|
||
- const showTitle = opts.showTitle !== false
|
||
- const showText = opts.showText !== false
|
||
- const showButton = !!opts.showButton
|
||
- const textBeforeImage = !!opts.textBeforeImage
|
||
- const center = !!opts.center
|
||
- const linkMode = !!opts.linkMode
|
||
- const linkHref = opts.linkHref || ''
|
||
- const linkText = opts.linkText || 'Как не терять наши письма?'
|
||
- const linkClass = opts.linkClass || 'text__link-blue'
|
||
|
||
tr
|
||
td.padding-wrapper(class=bgClass)
|
||
+defaultTable('560')
|
||
+spacerLine(40)
|
||
if showTitle && !textBeforeImage
|
||
tr
|
||
td(class=center ? 'text__center' : '')
|
||
span.textVerdana.header__h1(class=titleClass)= title
|
||
+spacerLine(20)
|
||
if showText && textBeforeImage
|
||
tr
|
||
td(class=center ? 'text__center' : '')
|
||
span.textVerdana.text__normal(class=textClass)= text
|
||
+spacerLine(20)
|
||
tr
|
||
td
|
||
+backgroundImageBlock(imageSrc, 560, 266, '#ffffff', 'left', 'top')
|
||
if showText && !textBeforeImage
|
||
+spacerLine(20)
|
||
tr
|
||
td(class=center ? 'text__center' : '')
|
||
span.textVerdana.text__normal(class=textClass)= text
|
||
if showButton
|
||
+spacerLine(20)
|
||
tr
|
||
td
|
||
if linkMode
|
||
a(href=linkHref target='_blank' style='width: 100%;').textVerdana(class=`${linkColorClass} text__link ${linkClass}`)= linkText
|
||
else
|
||
+buttonRounded('#ТЕКСТ#', '#ССЫЛКА#', 560, 60, buttonBg, 16, buttonText, 0, '').textVerdana
|
||
+spacerLine(40)
|
||
|
||
mixin contentCardImage270(opts = {})
|
||
- const title = opts.title || 'Контекстная реклама для увеличения продаж'
|
||
- const text = opts.text || 'Наша команда стала активнее участвовать в образовательных мероприятиях, на которых мы делимся тонкостями своей работы и рассказываем о практическом опыте. Решили поделиться с вами записями прошедших вебинаров. Вот сводка тем:'
|
||
- const imageSrc = opts.imageSrc || 'https://574922.selcdn.ru/email.static/reaspekt/master-tamplate/banners/image.jpg'
|
||
- const titleClass = opts.titleClass || 'color__blue'
|
||
- const textClass = opts.textClass || 'color__blue'
|
||
- const buttonBg = opts.buttonBg || '#ffffff'
|
||
- const buttonText = opts.buttonText || '#130F33'
|
||
- const showButton = !!opts.showButton
|
||
- const linkMode = !!opts.linkMode
|
||
- const linkHref = opts.linkHref || ''
|
||
- const linkText = opts.linkText || 'Как не терять наши письма?'
|
||
- const linkClass = opts.linkClass || 'text__link-blue'
|
||
- const linkColorClass = opts.linkColorClass || textClass
|
||
|
||
+defaultTable('270')
|
||
tr
|
||
td
|
||
+backgroundImageBlock(imageSrc, 270, 270, '#ffffff', 'left', 'top')
|
||
+spacerLine(20)
|
||
tr
|
||
td
|
||
span.textVerdana.header__h2(class=titleClass)= title
|
||
+spacerLine(20)
|
||
tr
|
||
td
|
||
span.textVerdana.text__normal(class=textClass)= text
|
||
if showButton
|
||
+spacerLine(20)
|
||
tr
|
||
td
|
||
if linkMode
|
||
a(href=linkHref target='_blank' style='width: 100%;').textVerdana(class=`${linkColorClass} text__link ${linkClass}`)= linkText
|
||
else
|
||
+buttonRounded('#ТЕКСТ#', '#ССЫЛКА#', 270, 60, buttonBg, 16, buttonText, 0, '').textVerdana
|
||
|
||
mixin textImageSection270(opts = {})
|
||
- const bgClass = opts.bgClass || 'background__white'
|
||
|
||
tr
|
||
td.padding-wrapper(class=bgClass)
|
||
+defaultTable('560')
|
||
+spacerLine(40, 3)
|
||
tr
|
||
td(valign='top')
|
||
+contentCardImage270(opts)
|
||
+tdFixed(20)
|
||
td(valign='top')
|
||
+contentCardImage270(opts)
|
||
+spacerLine(40, 3)
|
||
tr
|
||
td(valign='top')
|
||
+contentCardInner({
|
||
width: 173,
|
||
withImage: false,
|
||
titleSizeClass: 'header__h2',
|
||
titleClass: opts.titleClass,
|
||
textClass: opts.textClass,
|
||
buttonBg: opts.buttonBg,
|
||
buttonText: opts.buttonText,
|
||
firstColumnExtraGap: !!opts.firstColumnExtraGap
|
||
})
|
||
+tdFixed(20)
|
||
td(valign='top')
|
||
+contentCardInner({
|
||
width: 173,
|
||
withImage: false,
|
||
titleSizeClass: 'header__h2',
|
||
titleClass: opts.titleClass,
|
||
textClass: opts.textClass,
|
||
buttonBg: opts.buttonBg,
|
||
buttonText: opts.buttonText
|
||
})
|
||
+tdFixed(21)
|
||
td(valign='top')
|
||
+contentCardInner({
|
||
width: 173,
|
||
withImage: false,
|
||
titleSizeClass: 'header__h2',
|
||
titleClass: opts.titleClass,
|
||
textClass: opts.textClass,
|
||
buttonBg: opts.buttonBg,
|
||
buttonText: opts.buttonText
|
||
})
|
||
+spacerLine(40, 5)
|
||
|
||
mixin sideImageTextSection(opts = {})
|
||
- const bgClass = opts.bgClass || 'background__blue'
|
||
- const textClass = opts.textClass || 'color__white'
|
||
- const imageSrc = opts.imageSrc || 'https://574922.selcdn.ru/email.static/reaspekt/master-tamplate/banners/icons-box-blue.png'
|
||
- const imageBg = opts.imageBg || '#130F33'
|
||
- const text1 = opts.text1 || 'Искусственный интеллект может ускорить работу SEO-специалистов и оптимизировать затраты. Заменяет ли chatGPT копирайтера? Всем ли поможет такой подход? Об этом и не только узнайте по ссылке.'
|
||
- const text2 = opts.text2 || 'Наша команда стала активнее участвовать в образовательных мероприятиях, на которых мы делимся тонкостями своей работы....'
|
||
- const showSecondText = opts.showSecondText !== false
|
||
|
||
tr
|
||
td(class=bgClass)
|
||
+defaultTable('100%')
|
||
tr
|
||
td.paddingWrapper
|
||
+defaultTable('100%')
|
||
+spacerLine(40)
|
||
tr
|
||
td
|
||
span.textVerdana.text__normal(class=textClass)!= text1
|
||
if showSecondText
|
||
tr
|
||
td
|
||
span.textVerdana.text__normal(class=textClass)!= text2
|
||
+spacerLine(40)
|
||
td(valign='bottom')
|
||
+defaultTable('')
|
||
+trtd
|
||
+backgroundImageBlock(imageSrc, 145, 270, imageBg, 'center', 'top', 'contain')
|