PDFKit doesn't display custom font - ruby-on-rails-4

I am trying to use a custom font in a pdf I generate from html with PDFKit in my Rails app. I added the font in ...app/assets/fonts/ and included it in my html template:
css:
#font-face {
font-family: 'journal';
src: url(file://#{Rails.root.join('app', 'assets', 'fonts', 'journal.eot')});
src: url(file://#{Rails.root.join('app', 'assets', 'fonts', 'journal.woff')} format("woff")),
url(file://#{Rails.root.join('app', 'assets', 'fonts', 'journal.ttf')}) format("truetype");
}
called it in the css:
h1 {font-family: journal; }

don't use ; unless you're done declaring the rule. The universal CSS formatting here is:
selector {
propname: val1, val2, val3;
}
So you use , for multiple values, and then only at the very end a ;. What you've written instead does this:
selector {
src: some value;
src: some *overwriting* value;
}
Just declare your #font-face using the regular format and it should work fine:
#font-face {
font-family: 'journal';
src: url(file://#{Rails.root.join('app', 'assets', 'fonts', 'journal.eot')}),
url(file://#{Rails.root.join('app', 'assets', 'fonts', 'journal.woff')}) format("woff")),
url(file://#{Rails.root.join('app', 'assets', 'fonts', 'journal.ttf')}) format("truetype");
}
(note that you were also missing a ) for the "woff" case)
However, if you're targetting modern browsers, there is no reason to use eot anymore. IE9+ and everything else supports woff just fine. In fact, WOFF is a compressed opentype wrapper; browsers that support opentype also support WOFF, so trying to load both WOFF and ttf or otf makes no sense: see http://caniuse.com/woff

#font-face {
font-family: 'journalregular';
src: url(file://#{Rails.root.join('app', 'assets', 'fonts', 'journal-webfont.eot')});
}
#font-face {
font-family: 'journalregular';
src: url(file://#{Rails.root.join('app', 'assets', 'fonts', 'journal-webfont.woff')}) format('woff');
}
#font-face {
font-family: 'journalregular';
src: url(file://#{Rails.root.join('app', 'assets', 'fonts', 'journal-webfont.ttf')}) format('truetype');
}
#font-face {
font-family: 'journalregular';
src: url(file://#{Rails.root.join('app', 'assets', 'fonts', 'journal-webfont.svg#journalregular')}) format('svg');
}
#font-face {
font-family: 'journalregular';
font-weight: normal;
font-style: normal;
}
That seemed to fix it. Also, I needed to call it:
h1 { font-family: 'journalregular'; }

Related

Add file list, delete and download in ESP32 simple file server

It's the first time to ask a question, please forgive me if I am wrong.
English is not my native language; please excuse typing errors.
I am using ESP32 for the first time. I want to be a file server, but now it only has upload function. I want to add download, delete and file list. I have not been able to find suitable information. thank you.
ESP32 code:
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <SPI.h>
#include <SPIFFS.h>
void setup() {
Serial.begin(115200);
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
}
start_access_point();
start_web_server();
}
void loop()
{
}
const char* ap_ssid = "ESP32";
const char* ap_pwd = "12345678";
void start_access_point(){
WiFi.softAP(ap_ssid, ap_pwd);
IPAddress myIP = WiFi.softAPIP();
Serial.println("Access point started");
Serial.print("AP IP address: ");
Serial.println(myIP);
}
AsyncWebServer server(80);
const char* PARAM_SSID = "ssid";
const char* PARAM_PWD = "pwd";
void start_web_server(){
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", "text/html");
});
server.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request){
if(request->hasArg("file")){
String fileName = request->arg("file");
File f = SPIFFS.open("/data/fileName", "w");
if(!f){
request->send(500, "text/plain", "Could not open file for writing");
return;
}
std::string fileData = std::string(request->arg("file").c_str());
f.write((uint8_t*)fileData.c_str(), fileData.length());
f.close();
request->send(200, "text/plain", "File uploaded successfully");
}
else{
request->send(500, "text/plain", "No file data found in request");
}
});
server.begin();
}
HTML:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<style>.app-container{
border-radius: 5px;
background-color: #f2f2f2;
padding: 20px;
}
h3{
text-align: center;
color: #5a5c69 !important;
font-family: Arial, Helvetica, sans-serif;
}
/* Style inputs, select elements and textareas */
input[type=text], select, textarea{
width: 100%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
resize: vertical;
}
input[type=password], select, textarea{
width: 100%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
resize: vertical;
}
/* Style the label to display next to the inputs */
label {
padding: 12px 12px 12px 0;
display: inline-block;
}
/* Style the submit button */
input[type=submit] {
background-color: #4CAF50;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
float: right;
}
/* Floating column for labels: 25% width */
.col-25 {
float: left;
width: 25%;
margin-top: 6px;
}
/* Floating column for inputs: 75% width */
.col-75 {
float: left;
width: 75%;
margin-top: 6px;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* Responsive layout - when the screen is less than 600px wide, make the two columns stack on top of each other instead of next to each other */
#media screen and (max-width: 600px) {
.col-25, .col-75, input[type=submit] {
width: 100%;
margin-top: 0;
}
}
</style>
<title id="apptitle">Setup Wifi</title>
<head>
<title>File Upload</title>
</head>
<body>
<h1>File Upload</h1>
<form method="post" action="/upload" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="Upload" />
</form>
Download file
</body>
</html>
I tried to find a similar function modification on github, but there was no way
List. Simple iteration through all files in the data folder of esp32. Absolute path deletion before file name has to be done manually if you just want the file names:
#include "SPIFFS.h"
void setup() {
Serial.begin(115200);
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
File root = SPIFFS.open("/");
File file = root.openNextFile();
while(file){
Serial.print("FILE: ");
Serial.println(file.name());
file = root.openNextFile();
}
}
void loop() {}
Delete:
SPIFFS.remove(path); (all paths are absolute paths)
exists function to check if file exists
mkdir creating new folder
rmdir remove folder
opendir
rename
info
and more can be found here. just scroll down enough until you find them in the documentation:
https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html
Edit: Forgot to add download here. Download can be accomplished similarly to what you already have for your API:
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", "text/html");
});
It could send you to a new tab with the new link and use the response as a download buffer type thing. But change the type to the type of file you want. Im not quite sure what the name of the type was but i think it was something on the line of "binary/png" or something. you'd have to search that up

css modules query breaks css rules with latest css-loader

With css-loader
{
test: /\.s?css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader',
query: {
modules: true,
localIdentName: '[name]-[local]-[hash:base64:8]'
}
},
{ loader: 'sass-loader'}
]
}
configured that way the css-loader seems to not find css rules under class names. The css rules listed under div.profile doesn't get applied on the screen. The css-loader ver. 1.0.0 in my code runs with Node 10.x. Switching modules: false gets the desired styling to show.
The code is posted below.
main.js:
require('babel-runtime/regenerator');
require('babel-register');
require('webpack-hot-middleware/client?reload=true');
require('./index.html');
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Webpack 4</title>
</head>
<body>
<div class="profile">
<img src="./images/400.jpg" alt="">
<h1>Hello Webpack 4</h1>
<div id="react-root"></div>
</div>
<script src="/main-bundle.js"></script>
</body>
</html>
app.js:
import React from 'react';
import ReactDOM from 'react-dom';
import Counter from './counter';
import { AppContainer } from 'react-hot-loader';
const render = (Component) => {
ReactDOM.render(
<AppContainer>
<Component />
</AppContainer>,
document.getElementById('react-root')
);
};
render(Counter);
if (module.hot) {
module.hot.accept('./counter', () => {
render(require('./counter'));
});
}
counter.js:
import React, { Component } from 'react';
import { hot } from 'react-hot-loader';
import { css } from 'emotion';
import styled from 'react-emotion';
import styles from './main.scss';
const Fancy = styled('h1')`
color: ${props => props.wild ? 'hotpink' : 'gold'}
`;
const red = '#f00';
const className = css`
color: ${red};
font-size: 3rem;
`;
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
this.addCount = this.addCount.bind(this);
}
addCount() {
this.setState(() => ({ count: this.state.count + 1 }));
}
render() {
const isWild = this.state.count % 2 === 0;
return (
<div className={styles.counter}>
<h1 onClick={this.addCount} className={className}>Count: {this.state.count}</h1>
<Fancy wild={isWild}>react-emotion lib allows to hook styles to component names</Fancy>
</div>
);
}
}
export default hot(module)(Counter);
main.scss:
body {
background-color: #a1b2c3;
}
.profile {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
img {
border-radius: 50%;
box-shadow: 0 0 20px #000;
}
h1 {
font-family: 'source-code-pro', 'sans-serif';
font-weight: 400;
}
}
.counter {
border: 3px solid green;
}
The reason was the .profile class name in index.html is outside the counter.js scope. The css modules produce class names by the localIdentName pattern but the .profile class name was hard coded in index.html before css modules in counter.js came into play.
In counter.js
import styles from './main.scss';
console.log('styles:', styles);
outputs
styles: Object { profile: "main-profile-2P-yNf0J", counter: "main-counter-Pmp5YERO" }
How to get the main-profile-2P-yNf0J class name to index.html remains unclear for me.

Using scss with ionic

I am new to the ionic framework.I had written the code in scss and it is showing some bugs, I had tried to overcome the bugs but i can't.
Below is my scss code:
//colors
$grey: grey;
//fonts
$font_0: Arial;
$font_1: Helvetica;
$font_2: sans-serif;
page-home
{
.displayed: ;
}
.thicker {
font-size: 20px;
font-family: $font_0, $font_1, $font_2;
font-weight: 600;
text-align: center;
margin-top: 5px;
}
.input-label {
font-family: $font_0, $font_1, $font_2;
font-size: 14px;
text-align: center;
text-color: $grey;
}
Is there anyone to help me!!!!
There is an error in your SCSS :
page-home
{
.displayed: ;
}
This will not compile and will throw this error :
Invalid CSS after "{": expected "}", was ".displayed: ;"
When I switch it to :
page-home
{
}
Then it compiles.
https://ionicframework.com/docs/v2/theming/theming-your-app/
You should set the SCSS variables in the theme/variable.scss file when you require global access. All your individual scss files can use it.
page-home {}
"page-home" is your scss namespace for your pageHome.html. It is specified in your component(ts file). All css for that file should be within the namespace.
SCSS tutorial link: http://sass-lang.com/guide

Ho to install new font-family in a Zurb Founation project

Can you help me about how to add a new font-family in a Foundation project. This new font-family can be installed locally or external like Google Font Web.
Thank you.
You can create your mixin
#mixin font-face($style-name, $file, $family, $category:"") {
$filepath: "fonts/" + $family + "/" + $file;
#font-face {
font-family: "#{$style-name}";
src: url($filepath + ".eot");
src: url($filepath + ".eot?#iefix") format('embedded-opentype'), url($filepath + ".woff") format('woff'), url($filepath + ".ttf") format('truetype'), url($filepath + ".svg#" + $style-name + "") format('svg');
}
%#{$style-name} {
font: {
#if $category != "" {
family: "#{$style-name}", #{$category};
}
#else {
family: "#{$style-name}";
weight: normal;
}
}
}
}
And used it like this
#include font-face($style-name, $file, $family, $category);
Answer found quickly on the web...
<style>
#import url('https://fonts.googleapis.com/css?family=yourFontFamilyName');
</style>
Now use this font-family in inline css.
Style tag is removed by some webmail(for example gmail) so you can put it inside body.
If you are going to use foundation architecture then put the above line in foundation.css

List of items in Sass

I want to define a list of text input selectors in Sass such as:
[type="text"],
[type="color"],
[type="date"],
[type="datetime"],
[type="datetime-local"],
[type="email"],
[type="month"],
[type="number"],
[type="range"],
[type="search"],
[type="tel"],
[type="time"],
[type="url"],
[type="week"],
and then to use that list around my sass code. How can I set those as a variable and then to use them as above elsewhere?
Lists are worth learning about in SASS.
Addressing your need, let's define your list:
$text-input-selectors: "[type='text']" "[type='color']" "[type='date']"
"[type='datetime']" "[type='datetime-local']"
"[type='email']" "[type='month']" "[type='number']"
"[type='range']" "[type='search']" "[type='tel']"
"[type='time']" "[type='url']" "[type='week']";
We can run #each over it and get individual selectors:
#each $selector in $text-input-selectors {
#{$selector} {
font-weight: normal;
}
}
Result:
[type='text'] {
font-weight: normal;
}
[type='color'] {
font-weight: normal;
}
[type='date'] {
font-weight: normal;
}
[type='datetime'] {
font-weight: normal;
}
[type='datetime-local'] {
font-weight: normal;
}
[type='email'] {
font-weight: normal;
}
[type='month'] {
font-weight: normal;
}
[type='number'] {
font-weight: normal;
}
[type='range'] {
font-weight: normal;
}
[type='search'] {
font-weight: normal;
}
[type='tel'] {
font-weight: normal;
}
[type='time'] {
font-weight: normal;
}
[type='url'] {
font-weight: normal;
}
[type='week'] {
font-weight: normal;
}
Or we can run code that concatenates it to a comma separated string:
$all-selectors: null;
#each $item in $text-input-selectors {
$all-selectors: $all-selectors, unquote(#{$item});
}
#{$all-selectors} {
color: red;
}
Result:
[type='text'], [type='color'], [type='date'], [type='datetime'], [type='datetime-local'], [type='email'], [type='month'], [type='number'], [type='range'], [type='search'], [type='tel'], [type='time'], [type='url'], [type='week'] {
color: red;
}
I highly recommend Sassmeister for experimenting with SASS code. Can choose version to some extent, and use either SASS or SCSS.
You can use the #each directive:
$types: text, color, date, datetime, datetime-local, email, month, number, range, search, tel, time, url, week;
#each $prop in $types {
input[type="#{$prop}"] {
padding: 0;
// other meaningful properties
}
}
SassMeister demo
As mentioned by #cimmanon, it is true that there will be a lot of selectors which will make the css less readable. It is possible to use the trick from #artlung and combine all selectors into one:
$joined-selector: null;
#each $prop in $types {
$elem: "input[type='#{$prop}']";
$joined-selector: $joined-selector, $elem;
}
#{$joined-selector} {
padding: 0;
}
Updated SassMeister demo
That sass code looks rather complex to me. I prefer keeping sass simple and readable and sacrificing readability of the generated css file. As I developer I only maintain sass code, not the css.