Pull to refresh

Comments 17

Прошу прощения, но зачем подключать дополнительные языки, JVM, писать DSLы, если задача версии для печати давно уже легко решается средствами CSS?

Поиграть со стилями печати, скрыть всё что не нужно и надеяться, что всё будет хорошо. Только кнопки, фильтры и подобное распечатаются как есть. А ещё, если таблиц много, надо чтобы каждая была на отдельной странице. И лично меня бесят добавленные ссылки, даты и т.д., которые вылезают при печати с сайта

Все, что вы описали, легко можно сделать на CSS (а в связке с JS так вообще что угодно), есть Print Media Queries, которые с точностью до миллиметра спозиционируют любой элемент на странице. Вы ведь фронтэндер, CSS один из ваших основных инструментов, нужно лишь документацию поглубже почитать. Начните с лекции от сотрудника Яндекса, например: www.youtube.com/watch?v=xVPCZFBpjsI
Я, если честно, не знал, что есть page-break-before и page-break-inside.
К сожалению, это не решит всех проблем в моем случае. У меня упертый заказчик и ему нужна кнопка по которой скачивается PDF, а не открывается окно печати. Кроме того, не во всех браузерах получится конролировать ориентацию страницы.

PS Я не фронтендер на самом деле. Просто в этом проекте сложная админка и я его делаю один.
А это уже не сочетается с page-break-before и page-break-inside. Скорее всего, эта библиотека переводит HTML в canvas и превращает это в pdf
1) ага- jsPDF игнорирует css форматирование для печати.
Но вы можете использовать волшебный коммент
<!--ADD_PAGE-->
для разбиения страниц
2) pdf генерируется без участия canvas на основе HTML разметки страницы. Т е текст в pdf файле это действительно текст
3) Эта библиотека поддерживает печать только спецсимволов и латиницы. Для всего остального нужно юзать html2canvas

см пост jsPDF + canvas: экспорт в PDF многостраничной таблицы на русском языке
1) и как мне это комент вставлять, если я на react всё нарисовал?
3) спасибо за информацию. Категорическое нет для использования этой библиотеки в таком случае. Я и так не смог в своем вариенте символ рубля распечатать, но это я поленился нужный шрифт найти. А тут с кириллицей бороться.
Ну и на худой конец есть wkhtmltopdf, которому на вход можно подать страницу в stdin, а из stdout забрать байты pdf’а.
Из всех вариантов получить страницу в пдф, самым адекватным по тому что получается, по гибкости настроек мне показалось взять puppeteer. Из-за того что он тянет полный хром с собой (подводный камень), пдф получаются как если бы прямо нажать на печать страницы в хроме. wkhtmltopdf, например, делает из страницы какое-то месиво с кривым выделением. Также есть возможность настроить как угодно страницу, подсунуть любой скрипт и стиль.

Но, опять же из минусов, это жуткая неповоротливость. То есть имеет смысл держать демона с запущенным puppeter нежели вызывать его каждый раз.

пример на node.js
const puppeteer = require("puppeteer");
const path = require("path");
const base = __dirname;

(async () => {
	const browser = await puppeteer.launch({});
	const page = await browser.newPage();
	await page.goto("file://" + path.resolve(base, "index.html"));
	const height = await page.evaluate(
		() => document.documentElement.clientHeight
	);
	await page.pdf({
		path: path.resolve(base, "./output.pdf"),
		margin: {
			top: "2cm",
			bottom: "2cm",
			left: "1.5cm",
			right: "2cm",
		},
		height: `${height}px`,
	});

	await browser.close();
})().catch(e => {
	console.error(e);
});

т.е. мне надо будет отпавить всю текущую страницу на бек с настроеными стилями для печати? А как пробросить стили?
Я бы отправлял на бэк (микросервис на node со ждущим puppeteer) только ту часть страницы, которую составляет теоретический отчет. Прямо брал бы document.querySelector(".report").outerHTML и отправлял бы POST'om на сервер. А на сервере уже вставлял данный отчет в какой-то шаблон, с настроенными стилями и тд. В принципе стили можно на любом этапе присоединять.

Как добавить стили: github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageaddstyletagoptions

Опять же пример
const puppeteer = require("puppeteer");
const path = require("path");
const base = __dirname;

(async () => {
	const browser = await puppeteer.launch({});
	const page = await browser.newPage();
	await page.goto("file://" + path.resolve(base, "index.html"));
	const height = await page.evaluate(
		() => document.documentElement.clientHeight
	);
	await page.addStyleTag({
		content: `
			button {
				display: none;
			}
		`
	});
	await page.pdf({
		path: path.resolve(base, "./output.pdf"),
		margin: {
			top: "2cm",
			bottom: "2cm",
			left: "1.5cm",
			right: "2cm",
		},
		height: `${height}px`,
	});

	await browser.close();
})().catch(e => {
	console.error(e);
});

Так я ровно тоже самое делаю. Только бек у меня на java, а не node.

Но генерирую для этого html на лету, а не беру со страницы

UFO just landed and posted this here
UFO just landed and posted this here
Вы хотите сказать, что HTML — это не DSL? Или конфиг gradle — не DSL?
Вас, наверное, смущает слово language. Думаю, отличие DSL от набора функций в наличии своего синтакисиса/семантики. Так, возможность вызова тех или иных функций возможна только в опрделенном контексте. Код, написанный в это статье не позволяет вставить текст в tr или tr в td. К этому прибавляется минимизация чего-либо не связанного с доменной моделью.
Как яркий пример, можно написать DSL для тестирования в стиле BDD, который будет выглядеть вот так:
val button = ...
on click button check { ... }

Если это не новый маленький язык, то тогда DSL не существует.
UFO just landed and posted this here
Если что, в конфиг gradle можно вставлять любой код, который тебе заблогорассудится, потому что это просто groove код.

Именно жесткое сужение функционала делает ДСЛ полезным


Это действительно так. Но это же его минус. Сколько шаблонизаторов HTML? Сколько попыток сделать BDD фреймфорк? Все они имеют проблемы из-за того, что рано или поздно им требуется поддержка регулярного языка. От этого возникают специфичные конструкции для for, if и подобного (я боюсь считать сколько РАЗНЫХ вариантов for я видел на этом фоне, иногда по два в одном DSL).

С другой стороны оптимально спроектированный DSL будет иметь серьезные ограничения по использованию. На DSL по HTML от JetBrains, как я понял, нельзя нарисовать HTML, который не будет являться XHTML. В DSL по React не меньше ограничений, что и при использовании typeScript + React. И использование этих DSL в перемешку с регулярноым кодом будет просто дурным тоном, как дурной тон не отделять stateless компоненты в React и переносить логику в шаблонизаторы.
Sign up to leave a comment.

Articles