Release
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
"@babel/preset-env"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
["@babel/plugin-transform-runtime", {
|
||||||
|
"regenerator": true
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.html]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.{js,json,yml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
|
@ -0,0 +1,32 @@
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
browser: true,
|
||||||
|
},
|
||||||
|
extends: ["standard"],
|
||||||
|
rules: {
|
||||||
|
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||||
|
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||||
|
"comma-dangle": [2, "always-multiline"],
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ["**/__tests__/*.js", "**/tests/unit/**/*.spec.js"],
|
||||||
|
env: {
|
||||||
|
jest: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
parser: "babel-eslint"
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ["**/__tests__/*.js", "**/tests/unit/**/*.spec.js"],
|
||||||
|
env: {
|
||||||
|
jest: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
|
@ -0,0 +1,187 @@
|
||||||
|
|
||||||
|
# Created by https://www.gitignore.io/api/node,code,linux,macos,windows
|
||||||
|
# Edit at https://www.gitignore.io/?templates=node,code,linux,macos,windows
|
||||||
|
|
||||||
|
### Code ###
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### Node ###
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# nuxt.js build output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# rollup.js default build output
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# Uncomment the public line if your project uses Gatsby
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# https://create-react-app.dev/docs/using-the-public-folder/#docsNav
|
||||||
|
# public
|
||||||
|
|
||||||
|
# Storybook build outputs
|
||||||
|
.out
|
||||||
|
.storybook-out
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# Temporary folders
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
|
||||||
|
### Windows ###
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/node,code,linux,macos,windows
|
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) Ministère de l'intérieur
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,31 @@
|
||||||
|
# Générateur de certificat de déplacement
|
||||||
|
|
||||||
|
## Développer
|
||||||
|
|
||||||
|
### Installer le projet
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ git clone https://github.com/lab-mi/deplacement-codiv-19.git
|
||||||
|
$ cd deplacement-codiv-19
|
||||||
|
$ npm i
|
||||||
|
$ npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
### Générer le code de production
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Le code à déployer sera dans le dossier `dist`
|
||||||
|
|
||||||
|
## Crédits
|
||||||
|
|
||||||
|
Ce projet a été réalisé à partir d'un fork du dépôt [covid-19-certificate](https://github.com/nesk/covid-19-certificate) de [Johann Pardanaud](https://github.com/nesk).
|
||||||
|
|
||||||
|
Les projets open source suivants ont été utilisés pour le développement de ce service :
|
||||||
|
|
||||||
|
- [PDF-LIB](https://pdf-lib.js.org/)
|
||||||
|
- [qrcode](https://github.com/soldair/node-qrcode)
|
||||||
|
- [Bootstrap](https://getbootstrap.com/)
|
||||||
|
- [Font Awesome](https://fontawesome.com/license)
|
|
@ -0,0 +1,257 @@
|
||||||
|
import 'bootstrap/dist/css/bootstrap.min.css'
|
||||||
|
|
||||||
|
import { PDFDocument, StandardFonts } from 'pdf-lib'
|
||||||
|
import QRCode from 'qrcode'
|
||||||
|
|
||||||
|
import pdfBase from './certificate.pdf'
|
||||||
|
import './main.css'
|
||||||
|
|
||||||
|
const $ = (...args) => document.querySelector(...args)
|
||||||
|
const $$ = (...args) => [...document.querySelectorAll(...args)]
|
||||||
|
var year, month, day
|
||||||
|
|
||||||
|
const generateQR = async text => {
|
||||||
|
try {
|
||||||
|
var opts = {
|
||||||
|
errorCorrectionLevel: 'M',
|
||||||
|
type: 'image/png',
|
||||||
|
quality: 0.92,
|
||||||
|
margin: 1,
|
||||||
|
}
|
||||||
|
return await QRCode.toDataURL(text, opts)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pad (str) {
|
||||||
|
return String(str).padStart(2, '0')
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDateNow (date) {
|
||||||
|
year = date.getFullYear()
|
||||||
|
month = pad(date.getMonth() + 1) // Les mois commencent à 0
|
||||||
|
day = pad(date.getDate())
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', setReleaseDateTime)
|
||||||
|
|
||||||
|
function setReleaseDateTime () {
|
||||||
|
const loadedDate = new Date()
|
||||||
|
setDateNow(loadedDate)
|
||||||
|
const releaseDateInput = document.querySelector('#field-datesortie')
|
||||||
|
releaseDateInput.value = `${year}-${month}-${day}`
|
||||||
|
|
||||||
|
const hour = pad(loadedDate.getHours())
|
||||||
|
const minute = pad(loadedDate.getMinutes())
|
||||||
|
|
||||||
|
const releaseTimeInput = document.querySelector('#field-heuresortie')
|
||||||
|
releaseTimeInput.value = `${hour}:${minute}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveProfile () {
|
||||||
|
for (const field of $$('#form-profile input')) {
|
||||||
|
if (field.id === 'field-datesortie') {
|
||||||
|
var dateSortie = field.value.split('-')
|
||||||
|
localStorage.setItem(field.id.substring('field-'.length), `${dateSortie[2]}/${dateSortie[1]}/${dateSortie[0]}`)
|
||||||
|
} else {
|
||||||
|
localStorage.setItem(field.id.substring('field-'.length), field.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getProfile () {
|
||||||
|
const fields = {}
|
||||||
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
|
const name = localStorage.key(i)
|
||||||
|
fields[name] = localStorage.getItem(name)
|
||||||
|
}
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
function idealFontSize (font, text, maxWidth, minSize, defaultSize) {
|
||||||
|
let currentSize = defaultSize
|
||||||
|
let textWidth = font.widthOfTextAtSize(text, defaultSize)
|
||||||
|
|
||||||
|
while (textWidth > maxWidth && currentSize > minSize) {
|
||||||
|
textWidth = font.widthOfTextAtSize(text, --currentSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (textWidth > maxWidth) ? null : currentSize
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generatePdf (profile, reasons) {
|
||||||
|
const generatedDate = new Date()
|
||||||
|
setDateNow(generatedDate)
|
||||||
|
const creationDate = `${day}/${month}/${year}`
|
||||||
|
|
||||||
|
const hour = pad(generatedDate.getHours())
|
||||||
|
const minute = pad(generatedDate.getMinutes())
|
||||||
|
const creationHour = `${hour}h${minute}`
|
||||||
|
|
||||||
|
const { lastname, firstname, birthday, lieunaissance, address, zipcode, town, datesortie, heuresortie } = profile
|
||||||
|
const releaseHours = String(heuresortie).substring(0, 2)
|
||||||
|
const releaseMinutes = String(heuresortie).substring(3, 5)
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
`Cree le: ${creationDate} a ${creationHour}`,
|
||||||
|
`Nom: ${lastname}`,
|
||||||
|
`Prenom: ${firstname}`,
|
||||||
|
`Naissance: ${birthday} a ${lieunaissance}`,
|
||||||
|
`Adresse: ${address} ${zipcode} ${town}`,
|
||||||
|
`Sortie: ${datesortie} a ${releaseHours}h${releaseMinutes}`,
|
||||||
|
`Motifs: ${reasons}`,
|
||||||
|
].join('; ')
|
||||||
|
|
||||||
|
const existingPdfBytes = await fetch(pdfBase).then(res => res.arrayBuffer())
|
||||||
|
|
||||||
|
const pdfDoc = await PDFDocument.load(existingPdfBytes)
|
||||||
|
const page1 = pdfDoc.getPages()[0]
|
||||||
|
|
||||||
|
const font = await pdfDoc.embedFont(StandardFonts.Helvetica)
|
||||||
|
const drawText = (text, x, y, size = 11) => {
|
||||||
|
page1.drawText(text, { x, y, size, font })
|
||||||
|
}
|
||||||
|
|
||||||
|
drawText(`${firstname} ${lastname}`, 123, 686)
|
||||||
|
drawText(birthday, 123, 661)
|
||||||
|
drawText(lieunaissance, 92, 638)
|
||||||
|
drawText(`${address} ${zipcode} ${town}`, 134, 613)
|
||||||
|
|
||||||
|
if (reasons.includes('travail')) {
|
||||||
|
drawText('x', 76, 527, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('courses')) {
|
||||||
|
drawText('x', 76, 478, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('sante')) {
|
||||||
|
drawText('x', 76, 436, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('famille')) {
|
||||||
|
drawText('x', 76, 400, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('sport')) {
|
||||||
|
drawText('x', 76, 345, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('judiciaire')) {
|
||||||
|
drawText('x', 76, 298, 19)
|
||||||
|
}
|
||||||
|
if (reasons.includes('missions')) {
|
||||||
|
drawText('x', 76, 260, 19)
|
||||||
|
}
|
||||||
|
let locationSize = idealFontSize(font, profile.town, 83, 7, 11)
|
||||||
|
|
||||||
|
if (!locationSize) {
|
||||||
|
alert('Le nom de la ville risque de ne pas être affiché correctement en raison de sa longueur. ' +
|
||||||
|
'Essayez d\'utiliser des abréviations ("Saint" en "St." par exemple) quand cela est possible.')
|
||||||
|
locationSize = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
drawText(profile.town, 111, 226, locationSize)
|
||||||
|
|
||||||
|
if (reasons !== '') {
|
||||||
|
// Date sortie
|
||||||
|
drawText(`${profile.datesortie}`, 92, 200)
|
||||||
|
drawText(releaseHours, 200, 201)
|
||||||
|
drawText(releaseMinutes, 220, 201)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Date création
|
||||||
|
drawText('Date de création:', 464, 150, 7)
|
||||||
|
drawText(`${creationDate} à ${creationHour}`, 455, 144, 7)
|
||||||
|
|
||||||
|
const generatedQR = await generateQR(data)
|
||||||
|
|
||||||
|
const qrImage = await pdfDoc.embedPng(generatedQR)
|
||||||
|
|
||||||
|
page1.drawImage(qrImage, {
|
||||||
|
x: page1.getWidth() - 170,
|
||||||
|
y: 155,
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
})
|
||||||
|
|
||||||
|
pdfDoc.addPage()
|
||||||
|
const page2 = pdfDoc.getPages()[1]
|
||||||
|
page2.drawImage(qrImage, {
|
||||||
|
x: 50,
|
||||||
|
y: page2.getHeight() - 350,
|
||||||
|
width: 300,
|
||||||
|
height: 300,
|
||||||
|
})
|
||||||
|
|
||||||
|
const pdfBytes = await pdfDoc.save()
|
||||||
|
|
||||||
|
return new Blob([pdfBytes], { type: 'application/pdf' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadBlob (blob, fileName) {
|
||||||
|
const link = document.createElement('a')
|
||||||
|
var url = URL.createObjectURL(blob)
|
||||||
|
link.href = url
|
||||||
|
link.download = fileName
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAndSaveReasons () {
|
||||||
|
const values = $$('input[name="field-reason"]:checked')
|
||||||
|
.map(x => x.value)
|
||||||
|
.join('-')
|
||||||
|
localStorage.setItem('reasons', values)
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// see: https://stackoverflow.com/a/32348687/1513045
|
||||||
|
function isFacebookBrowser () {
|
||||||
|
const ua = navigator.userAgent || navigator.vendor || window.opera
|
||||||
|
return ua.includes('FBAN') || ua.includes('FBAV')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFacebookBrowser()) {
|
||||||
|
$('#alert-facebook').classList.remove('d-none')
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSlash () {
|
||||||
|
this.value = this.value.replace(/^(\d{2})$/g, '$1/')
|
||||||
|
this.value = this.value.replace(/^(\d{2})\/(\d{2})$/g, '$1/$2/')
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#field-birthday').addEventListener('keyup', addSlash)
|
||||||
|
|
||||||
|
const snackbar = $('#snackbar')
|
||||||
|
|
||||||
|
$('#form-profile').addEventListener('submit', async event => {
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
saveProfile()
|
||||||
|
const reasons = getAndSaveReasons()
|
||||||
|
const pdfBlob = await generatePdf(getProfile(), reasons)
|
||||||
|
downloadBlob(pdfBlob, 'attestation.pdf')
|
||||||
|
|
||||||
|
snackbar.classList.remove('d-none')
|
||||||
|
setTimeout(() => snackbar.classList.add('show'), 100)
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
snackbar.classList.remove('show')
|
||||||
|
setTimeout(() => snackbar.classList.add('d-none'), 500)
|
||||||
|
}, 6000)
|
||||||
|
})
|
||||||
|
|
||||||
|
$$('input').forEach(input => {
|
||||||
|
const exempleElt = input.parentNode.parentNode.querySelector('.exemple')
|
||||||
|
if (input.placeholder && exempleElt) {
|
||||||
|
input.addEventListener('input', (event) => {
|
||||||
|
if (input.value) {
|
||||||
|
exempleElt.innerHTML = 'ex. : ' + input.placeholder
|
||||||
|
} else {
|
||||||
|
exempleElt.innerHTML = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function addVersion () {
|
||||||
|
document.getElementById('version').innerHTML = `${new Date().getFullYear()} - ${process.env.VERSION}`
|
||||||
|
}
|
||||||
|
addVersion()
|
|
@ -0,0 +1,188 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
<meta name="msapplication-TileColor" content="#603cba" />
|
||||||
|
<meta name="msapplication-config" content="./favicons/browserconfig.xml" />
|
||||||
|
<meta name="theme-color" content="#ffffff" />
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="./favicons/apple-touch-icon.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicons/favicon-32x32.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="./favicons/favicon-16x16.png" />
|
||||||
|
<link rel="manifest" href="./favicons/site.webmanifest" />
|
||||||
|
<link rel="mask-icon" href="./favicons/safari-pinned-tab.svg" color="#21bf73" />
|
||||||
|
|
||||||
|
<title>COVID-19 – Générateur d'attestation de déplacement</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="confidentialite">
|
||||||
|
<div class="container">
|
||||||
|
<header class="wrapper">
|
||||||
|
<img class="logo" src="/MIN_Interieur_RVB.svg" alt="logo_ministère_interieur" />
|
||||||
|
<div class="header-content">
|
||||||
|
<h1 class="flex flex-wrap">
|
||||||
|
<div class="covid-title">
|
||||||
|
COVID-19
|
||||||
|
</div>
|
||||||
|
<div class="covid-subtitle">
|
||||||
|
Générateur d'attestation de déplacement
|
||||||
|
</div>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div class="wrapper">
|
||||||
|
<h2 class="titre-2">Politique de confidentialité</h2>
|
||||||
|
<h3 class="titre-3">Collecte des données personnelles</h3>
|
||||||
|
<p>
|
||||||
|
Les informations saisies dans ce générateur d’attestation de
|
||||||
|
déplacement ne font l’objet d’aucune collecte par le ministère
|
||||||
|
de l’Intérieur. Ces données personnelles<sup>1</sup> sont
|
||||||
|
exclusivement stockées dans le terminal (ordinateur, tablette,
|
||||||
|
smartphone) utilisé pour générer l’attestation.
|
||||||
|
</p>
|
||||||
|
<em>1 - Prénom, Nom, Date de naissance, Lieu de naissance, Adresse,
|
||||||
|
Code postal, Ville.</em>
|
||||||
|
<h3 class="titre-3">Traceurs et cookies</h3>
|
||||||
|
<p>
|
||||||
|
Lors de la consultation du générateur, des cookies sont déposés
|
||||||
|
sur le terminal utilisé. Ces cookies sont utilisés pour
|
||||||
|
sécuriser le service proposé.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 class="titre-4">Définition d’un cookie</h4>
|
||||||
|
<p>
|
||||||
|
Un "cookie" est une suite d'informations, généralement de petite
|
||||||
|
taille et identifié par un nom, qui peut être transmis à votre
|
||||||
|
navigateur par un site web sur lequel vous vous connectez. Votre
|
||||||
|
navigateur web le conserve pendant une certaine durée, et le
|
||||||
|
renvoie au serveur web chaque fois que vous vous y
|
||||||
|
re-connecterez. Les cookies ont de multiples usages : ils
|
||||||
|
peuvent servir à mémoriser votre identifiant client auprès d'un
|
||||||
|
site marchand, le contenu courant de votre panier d'achat, un
|
||||||
|
identifiant permettant de tracer votre navigation pour des
|
||||||
|
finalités statistiques ou publicitaires, etc.
|
||||||
|
</p>
|
||||||
|
<h4 class="titre-4">Cookies utilisés</h4>
|
||||||
|
<p>
|
||||||
|
Différents cookies techniques sont utilisés sur ce générateur
|
||||||
|
d’attestation de déplacement :
|
||||||
|
</p>
|
||||||
|
<table class="cookies">
|
||||||
|
<thead>
|
||||||
|
<tr class="header-row">
|
||||||
|
<th>Nom du Cookie</th>
|
||||||
|
<th>Finalité</th>
|
||||||
|
<th>Durée de conservation</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td data-label="Nom du Cookie" class="name-col">incap_ses_*</td>
|
||||||
|
<td data-label="Finalité" >
|
||||||
|
Protection DDoS Incapsula et Pare-feu pour application
|
||||||
|
web : cookie servant à relier les requêtes HTTP à une
|
||||||
|
session. La réouverture du navigateur et l’accès au même
|
||||||
|
site sont considérés comme des visites différentes. Pour
|
||||||
|
maintenir les sessions existantes (cookie de session).
|
||||||
|
</td>
|
||||||
|
<td data-label="Durée de conservation" >Supprimé après la fermeture du navigateur.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td data-label="Nom du Cookie" class="name-col">nlbi_*</td>
|
||||||
|
<td data-label="Finalité" >
|
||||||
|
Protection DDoS Incapsula et Pare-feu pour application
|
||||||
|
web : cookie équilibreur de charge qui garantit que les
|
||||||
|
requêtes d’un client sont envoyées au même serveur
|
||||||
|
d’origine.
|
||||||
|
</td>
|
||||||
|
<td data-label="Durée de conservation" >Supprimé après la fermeture du navigateur.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td data-label="Nom du Cookie" class="name-col">visid_incap_*</td>
|
||||||
|
<td data-label="Finalité" >
|
||||||
|
Protection DDoS Incapsula et Pare-feu pour application
|
||||||
|
web : cookie servant à relier certaines sessions à un
|
||||||
|
visiteur spécifique (visiteur représentant un ordinateur
|
||||||
|
spécifique). Afin d’identifier les clients ayant déjà
|
||||||
|
consulté Incapsula. Le seul cookie qui perdure pour une
|
||||||
|
durée de 12 mois.
|
||||||
|
</td>
|
||||||
|
<td data-label="Durée de conservation" >12 mois.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td data-label="Nom du Cookie" class="name-col">__utm*</td>
|
||||||
|
<td data-label="Finalité" >
|
||||||
|
Cookie de classification Incapsula : pour voir comment
|
||||||
|
le client réagit à et gère un cookie mal formé afin
|
||||||
|
d’identifier la nature de ce client.
|
||||||
|
</td>
|
||||||
|
<td data-label="Durée de conservation" >900 secondes maximum.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Vous pouvez refuser ces cookies en configurant les paramètres de
|
||||||
|
votre navigateur.
|
||||||
|
</p>
|
||||||
|
<h4 class="titre-4">
|
||||||
|
Moyens d'opposition au dépôt des cookies via votre navigateur
|
||||||
|
</h4>
|
||||||
|
<p>
|
||||||
|
<strong>Si vous utilisez Firefox : </strong>Cliquez sur le
|
||||||
|
bouton de menu et sélectionnez « Options ». Ensuite,
|
||||||
|
sélectionnez le panneau « Vie privée et sécurité ». Rendez-vous
|
||||||
|
à la section « Protection renforcée contre le pistage ».
|
||||||
|
Choisissez la protection personnalisé [bouton radio
|
||||||
|
« Personnalisé »]. Décochez la case « cookies ». Cliquez sur le
|
||||||
|
bouton « Actualisez tous les onglets » si vous souhaitez
|
||||||
|
appliquer ces changements à la navigation en cours au sein de
|
||||||
|
votre navigateur.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Si vous utilisez Chrome : </strong>En haut à droite,
|
||||||
|
cliquez sur « Plus > Paramètres ». En bas, cliquez sur «
|
||||||
|
Paramètres avancés ». Dans la section "Confidentialité et
|
||||||
|
sécurité", cliquez sur « Paramètres des sites». Cliquez sur «
|
||||||
|
Cookies et données des sites». Désactivez l’option « Autoriser
|
||||||
|
les sites à enregistrer/lire les données des cookies ».
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Si vous utilisez Internet Explorer : </strong>Sélectionnez le bouton « Outils », puis « Options
|
||||||
|
Internet ».
|
||||||
|
Sélectionnez l’onglet « Confidentialité » puis sous « Paramètres
|
||||||
|
», sélectionnez « Avancé ». Cochez la case "Ignorer la gestion
|
||||||
|
automatique des cookies", puis sélectionner "Refuser" dans la
|
||||||
|
colonne "Cookies tierces parties".
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Pour plus d’informations sur le sujet, n’hésitez pas à visiter
|
||||||
|
le
|
||||||
|
<a href="https://www.cnil.fr/fr/cookies-et-autres-traceurs">site de la CNIL</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="btn-wrapper">
|
||||||
|
<a href="./index.html" class="btn-generateur">
|
||||||
|
Retour au générateur
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="main-footer">
|
||||||
|
<div class="footer-links">
|
||||||
|
<a class="footer-link">Confidentialité</a>
|
||||||
|
<a href="https://www.interieur.gouv.fr/Infos-du-site/Mentions-legales" target="_blank" title="Mentions légales - nouvelle page"
|
||||||
|
class="footer-link">Mentions légales</a>
|
||||||
|
<a href="https://www.gouvernement.fr/info-coronavirus" target="_blank" title="Information du gouvernement sur le Covid-19 - nouvelle page" class="footer-link">Informations du
|
||||||
|
gouvernement sur le Covid-19</a>
|
||||||
|
<p class="footer-link">
|
||||||
|
Plus d’infos au<a class="num-08" href="tel:0800130000">
|
||||||
|
0 800 130 000</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
<script src="./confidentialite.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,2 @@
|
||||||
|
import 'bootstrap/dist/css/bootstrap.min.css'
|
||||||
|
import './main.css'
|
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 10 KiB |
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig>
|
||||||
|
<msapplication>
|
||||||
|
<tile>
|
||||||
|
<square150x150logo src="mstile-150x150.png"/>
|
||||||
|
<TileColor>#603cba</TileColor>
|
||||||
|
</tile>
|
||||||
|
</msapplication>
|
||||||
|
</browserconfig>
|
After Width: | Height: | Size: 613 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="1024.000000pt" height="1024.000000pt" viewBox="0 0 1024.000000 1024.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<metadata>
|
||||||
|
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||||
|
</metadata>
|
||||||
|
<g transform="translate(0.000000,1024.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M4858 10236 c-1 -2 -50 -6 -108 -10 -58 -3 -116 -8 -130 -11 -14 -2
|
||||||
|
-52 -7 -85 -10 -105 -9 -381 -52 -395 -60 -3 -2 -26 -6 -50 -10 -25 -4 -126
|
||||||
|
-27 -225 -52 -661 -165 -1268 -457 -1830 -879 -82 -62 -161 -123 -175 -136
|
||||||
|
-14 -13 -55 -48 -90 -78 -243 -205 -529 -511 -739 -790 -39 -52 -75 -100 -80
|
||||||
|
-106 -22 -27 -153 -228 -218 -334 -178 -293 -340 -637 -453 -965 -69 -202
|
||||||
|
-140 -458 -174 -635 -2 -14 -9 -47 -15 -75 -13 -62 -20 -106 -55 -360 -37
|
||||||
|
-258 -43 -912 -11 -1106 2 -13 6 -51 10 -84 3 -33 8 -76 10 -95 11 -75 27
|
||||||
|
-176 32 -205 3 -16 7 -39 8 -50 7 -43 16 -89 20 -94 2 -4 6 -24 9 -46 6 -38
|
||||||
|
50 -211 95 -375 93 -339 299 -812 504 -1155 105 -175 101 -169 107 -175 3 -3
|
||||||
|
27 -39 54 -80 50 -77 254 -351 301 -405 14 -16 49 -57 78 -90 149 -172 466
|
||||||
|
-486 549 -543 13 -9 32 -25 43 -35 92 -87 397 -307 599 -432 309 -190 707
|
||||||
|
-377 1035 -485 206 -68 328 -103 400 -117 14 -2 28 -6 31 -8 5 -3 121 -28 231
|
||||||
|
-50 56 -11 257 -45 299 -50 289 -35 363 -39 675 -39 245 -1 407 5 510 19 17 2
|
||||||
|
59 7 95 10 36 4 74 9 85 11 11 1 40 6 65 9 81 11 257 44 377 71 65 14 124 27
|
||||||
|
133 29 8 2 56 15 105 30 50 15 106 31 125 36 56 14 255 83 380 132 260 103
|
||||||
|
475 207 735 357 160 92 510 340 675 478 218 182 544 511 671 677 13 17 26 32
|
||||||
|
29 35 14 11 143 183 212 280 66 94 228 346 228 355 0 2 20 37 44 77 45 77 188
|
||||||
|
360 220 438 11 25 27 63 37 85 125 284 284 828 325 1115 3 19 7 46 9 60 12 62
|
||||||
|
23 148 31 225 3 33 7 71 10 85 25 158 25 830 -1 1020 -8 63 -16 129 -21 174
|
||||||
|
-3 27 -6 52 -8 55 -2 3 -7 31 -11 61 -3 30 -8 62 -10 70 -2 8 -7 29 -9 45 -3
|
||||||
|
17 -10 55 -16 85 -6 30 -14 66 -16 80 -44 226 -187 679 -284 895 -10 22 -32
|
||||||
|
74 -50 115 -51 118 -200 404 -280 535 -221 366 -482 698 -781 995 -113 113
|
||||||
|
-258 245 -332 303 -15 12 -39 32 -52 44 -36 32 -280 213 -350 260 -387 258
|
||||||
|
-753 444 -1160 588 -242 86 -581 177 -780 209 -36 6 -82 14 -110 20 -11 2 -45
|
||||||
|
7 -75 11 -30 4 -62 9 -71 10 -29 6 -116 15 -294 32 -50 4 -642 12 -647 9z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"short_name": "",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "android-chrome-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#ffffff",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
|
@ -0,0 +1,273 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="msapplication-TileColor" content="#603cba">
|
||||||
|
<meta name="msapplication-config" content="./favicons/browserconfig.xml">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
<meta name="title" content="Générateur d'attestation de déplacement dérogatoire - COVID-19">
|
||||||
|
<meta name="description" content="Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle.">
|
||||||
|
<meta name="keywords" content="covid19, covid-19, attestation, déplacement, officielle, gouvernement">
|
||||||
|
<meta name="robots" content="index, follow">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<meta name="language" content="French">
|
||||||
|
<meta property="og:title" content="Générateur d'attestation de déplacement dérogatoire - COVID-19" />
|
||||||
|
<meta property="og:locale" content="fr_FR" />
|
||||||
|
<meta property="og:description" content="Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle." />
|
||||||
|
<link rel="canonical" href="https://media.interieur.gouv.fr/deplacement-covid-19/" />
|
||||||
|
<meta property="og:url" content="https://media.interieur.gouv.fr/deplacement-covid-19/" />
|
||||||
|
<meta property="og:site_name" content="Générateur d'attestation de déplacement dérogatoire - COVID-19" />
|
||||||
|
<script type='application/ld+json'>{"@context":"http://www.schema.org","@type":"GovernmentOrganization","name":"Générateur d'attestation de déplacement dérogatoire - COVID-19","description":"Ce service officiel génère une version numérique de l’attestation déplacement covid-19 à présenter aux forces de sécurité lors d’un contrôle.","address":{"@type":"PostalAddress","addressCountry":"France"}}</script>
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="./favicons/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicons/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="./favicons/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="./favicons/site.webmanifest">
|
||||||
|
<link rel="mask-icon" href="./favicons/safari-pinned-tab.svg" color="#21bf73">
|
||||||
|
|
||||||
|
<title>COVID-19 – Générateur d'attestation de déplacement dérogatoire</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class="wrapper">
|
||||||
|
<img class="logo" src="/MIN_Interieur_RVB.svg" alt="">
|
||||||
|
<div>
|
||||||
|
<h1 class="flex flex-wrap">
|
||||||
|
<span class="covid-title">
|
||||||
|
COVID-19
|
||||||
|
</span>
|
||||||
|
<span class="covid-subtitle">
|
||||||
|
Générateur d'attestation de déplacement dérogatoire
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
<p class="text-alert">
|
||||||
|
Les données saisies sont stockées exclusivement sur votre téléphone ou votre ordinateur. Aucune information n'est collectée par le Ministère de l'Intérieur.
|
||||||
|
L'attestation pdf générée contient un QR Code. Ce code-barres graphique permet de lire les informations portées dans votre attestation au moment de leur saisie.
|
||||||
|
Il peut être déchiffré à l'aide de tout type de lecteur de QR code générique.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<form id="form-profile">
|
||||||
|
<h2 class="titre-2">Remplissez en ligne votre attestation numérique :</h2>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-firstname" id="field-firstname-label">Prénom</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-firstname"
|
||||||
|
name="firstname"
|
||||||
|
autocomplete="given-name"
|
||||||
|
placeholder="Jean"
|
||||||
|
aria-labelledby="field-firstname-label"
|
||||||
|
required
|
||||||
|
autofocus
|
||||||
|
>
|
||||||
|
<span class="validity"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-lastname" id="field-lastname-label">Nom</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-lastname"
|
||||||
|
name="lastname"
|
||||||
|
autocomplete="family-name"
|
||||||
|
placeholder="Dupont"
|
||||||
|
aria-labelledby="field-lastname-label"
|
||||||
|
required
|
||||||
|
autofocus
|
||||||
|
>
|
||||||
|
<span class="validity"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-birthday" id="field-birthday-label">Date de naissance (au format jj/mm/aaaa)</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
inputmode="numeric"
|
||||||
|
class="form-control"
|
||||||
|
id="field-birthday"
|
||||||
|
name="birthday"
|
||||||
|
autocomplete="bday"
|
||||||
|
placeholder="01/01/1970"
|
||||||
|
maxlength="10"
|
||||||
|
aria-labelledby="field-birthday-label"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-lieunaissance" id="field-lieunaissance-label">Lieu de naissance</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-lieunaissance"
|
||||||
|
name="lieunaissance"
|
||||||
|
aria-labelledby="field-lieunaissance-label"
|
||||||
|
placeholder="Lyon"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-address" id="field-address-label">Adresse</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-address"
|
||||||
|
name="address"
|
||||||
|
autocomplete="address-line1"
|
||||||
|
aria-labelledby="field-address-label"
|
||||||
|
placeholder="999 avenue de france"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-town" id="field-town-label">Ville</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="field-town"
|
||||||
|
name="town"
|
||||||
|
autocomplete="address-level1"
|
||||||
|
aria-labelledby="field-town-label"
|
||||||
|
placeholder="Paris"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-zipcode" id="field-zipcode-label" >Code Postal</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="00000"
|
||||||
|
max="99999"
|
||||||
|
class="form-control"
|
||||||
|
id="field-zipcode"
|
||||||
|
name="zipcode"
|
||||||
|
autocomplete="zipcode"
|
||||||
|
minlength="4"
|
||||||
|
maxlength="5"
|
||||||
|
aria-labelledby="field-zipcode-label"
|
||||||
|
placeholder="75001"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="validity"></span>
|
||||||
|
</div>
|
||||||
|
<p class="exemple"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Choisissez un motif de sortie</h3>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-travail" value="travail">
|
||||||
|
<label class="form-check-label" for="checkbox-travail">Déplacements entre le domicile et le lieu d’exercice de l’activité professionnelle, lorsqu'ils sont indispensables à l'exercice d’activités ne pouvant être organisées sous forme de télétravail ou déplacements professionnels ne pouvant être différés.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-courses" value="courses">
|
||||||
|
<label class="form-check-label" for="checkbox-courses">Déplacements pour effectuer des achats de fournitures nécessaires à l’activité professionnelle et des achats de première nécessité dans des établissements dont les activités demeurent autorisées <a href="https://www.service-public.fr/particuliers/actualites/A13921" target="_blank">(liste sur gouvernement.fr)</a>.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-sante" value="sante">
|
||||||
|
<label class="form-check-label" for="checkbox-sante">Consultations et soins ne pouvant être assurés à distance et ne pouvant être différés ; consultations et soins des patients atteints d'une affection de longue durée.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-famille" value="famille">
|
||||||
|
<label class="form-check-label" for="checkbox-famille">Déplacements pour motif familial impérieux, pour l’assistance aux personnes vulnérables ou la garde d’enfants.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-sport" value="sport">
|
||||||
|
<label class="form-check-label" for="checkbox-sport">Déplacements brefs, dans la limite d'une heure quotidienne et dans un rayon maximal d'un kilomètre autour du domicile, liés soit à l'activité physique individuelle des personnes, à l'exclusion de toute pratique sportive collective et de toute proximité avec d'autres personnes, soit à la promenade avec les seules personnes regroupées dans un même domicile, soit aux besoins des animaux de compagnie.</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-judiciaire" value="judiciaire">
|
||||||
|
<label class="form-check-label" for="checkbox-judiciaire">Convocation judiciaire ou administrative.</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="field-reason" id="checkbox-missions" value="missions">
|
||||||
|
<label class="form-check-label" for="checkbox-missions">Participation à des missions d’intérêt général sur demande de l’autorité administrative.</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-datesortie">Date de sortie</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input type="date" class="form-control" id="field-datesortie" name="datesortie" placeholder="JJ/MM/YYYY" required>
|
||||||
|
<span class="validity"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="field-heure">Heure de sortie</label>
|
||||||
|
<div class="input-group align-items-center">
|
||||||
|
<input type="time" class="form-control" id="field-heuresortie" name="heure" required>
|
||||||
|
<span class="validity"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<p class="text-center mt-5">
|
||||||
|
<button type="submit" class="btn btn-primary btn-attestation"> <span class="btn-text">Générer mon attestation</span></button>
|
||||||
|
</p>
|
||||||
|
<div class="bg-primary d-none" id="snackbar">
|
||||||
|
L'attestation est téléchargée sur votre appareil.
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
|
<p class="label-mi">
|
||||||
|
Ministère de l'Intérieur - DNUM - SDIT
|
||||||
|
</p>
|
||||||
|
<img class="center" src="/logo_dnum.svg" alt="logo dnum">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="main-footer">
|
||||||
|
<div class="footer-links">
|
||||||
|
<a href="./confidentialite.html" title="Confidentialité - nouvelle page" target="_blank" class="footer-link">Confidentialité</a>
|
||||||
|
<a href="https://www.interieur.gouv.fr/Infos-du-site/Mentions-legales" title="Mentions légales - nouvelle page" target="_blank" class="footer-link">Mentions légales</a>
|
||||||
|
<a href="https://www.gouvernement.fr/info-coronavirus" title="Information du gouvernement sur le Covid-19 - nouvelle page" target="_blank" class="footer-link">Informations du gouvernement sur le Covid-19</a>
|
||||||
|
<div class="footer-link" >Plus d’infos au<a class="num-08" href="tel:0800130000"> 0 800 130 000</a></div>
|
||||||
|
<p class="footer-link" id="version"></p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<div class="alert alert-danger d-none" role="alert" id="alert-facebook">
|
||||||
|
ATTENTION !! Vous utilisez actuellement le navigateur Facebook, ce générateur ne fonctionne pas correctement au
|
||||||
|
sein de ce navigateur ! Merci d'ouvrir Chrome sur Android ou bien Safari sur iOS.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="./certificate.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
After Width: | Height: | Size: 49 KiB |
|
@ -0,0 +1,367 @@
|
||||||
|
@font-face {
|
||||||
|
font-family: 'marianne-bold';
|
||||||
|
src: url('./fonts/marianne-bold-webfont.woff2') format('woff2'),
|
||||||
|
url('./fonts/marianne-bold-webfont.woff') format('woff');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'marianne-regular';
|
||||||
|
src: url('./fonts/marianne-regular-webfont.woff2') format('woff2'),
|
||||||
|
url('./fonts/marianne-regular-webfont.woff') format('woff');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form, #alert-print {
|
||||||
|
margin: 30px auto;
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Small devices (landscape phones, 576px and up) */
|
||||||
|
@media (min-width: 576px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Medium devices (tablets, 768px and up) */
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 3em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.flex.flex-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: large;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-radius: .25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
max-width: 800px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#form-profile .form-check {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#form-profile .form-check-label {
|
||||||
|
font-weight: 400;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#form-generate .form-check {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#alert-facebook {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#alert-print {
|
||||||
|
margin: 1rem auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#date-selector-group {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#date-selector-group-sortie {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#date-selector {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 50%;
|
||||||
|
height: 100%;
|
||||||
|
transform: translateX(-50%); /* center the input to avoid reset buttons */
|
||||||
|
opacity: 0;
|
||||||
|
z-index: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#date-selector-sortie {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 50%;
|
||||||
|
height: 100%;
|
||||||
|
transform: translateX(-50%); /* center the input to avoid reset buttons */
|
||||||
|
opacity: 0;
|
||||||
|
z-index: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:invalid+span:after {
|
||||||
|
content: '✖';
|
||||||
|
padding-left: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:valid+span:after {
|
||||||
|
content: '✓';
|
||||||
|
padding-left: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
::placeholder {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.exemple {
|
||||||
|
margin-top: 0.2em;
|
||||||
|
font-style: italic;
|
||||||
|
color: #999999;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.covid-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.3em;
|
||||||
|
font-family: 'marianne-regular', Arial, Helvetica, sans-serif;
|
||||||
|
font-size: 0.50em;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #000191;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.covid-title {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.covid-subtitle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.40em;
|
||||||
|
padding: 0.3em;
|
||||||
|
background-color: #e1000f;
|
||||||
|
text-transform:uppercase ;
|
||||||
|
color: #ffffff;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-alert{
|
||||||
|
text-align: left;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.btn-attestation {
|
||||||
|
padding: 0.8em;
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #000191;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.github {
|
||||||
|
font-size: 0.7em;
|
||||||
|
text-align: center;
|
||||||
|
color: #000000;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.github-link {
|
||||||
|
color: #000191;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-mi {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1em;
|
||||||
|
color: #000000
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 3em;
|
||||||
|
padding-bottom: 3em;
|
||||||
|
background-color:#000000;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links {
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-link {
|
||||||
|
display: block;
|
||||||
|
margin: 0.75em;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-link:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-link:focus {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.num-08 {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #00a94f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confidentialite {
|
||||||
|
.cookies {
|
||||||
|
border-collapse: collapse;
|
||||||
|
|
||||||
|
td,
|
||||||
|
th {
|
||||||
|
border: 1px solid #000191;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-row {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #000191;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-col {
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 8px 16px;
|
||||||
|
color: #000191;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.btn-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.btn-generateur {
|
||||||
|
padding: 0.8em;
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #000191;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
em {
|
||||||
|
font-size: .8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.titre-2 {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #000191;
|
||||||
|
}
|
||||||
|
.titre-3 {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
.titre-4 {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 800px){
|
||||||
|
table thead {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr{
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td {
|
||||||
|
display: flex;
|
||||||
|
text-align: left;
|
||||||
|
min-height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td:before {
|
||||||
|
content: attr(data-label);
|
||||||
|
font-weight: bold;
|
||||||
|
color: #000191;
|
||||||
|
width: 100px;
|
||||||
|
margin-right: 8px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#snackbar {
|
||||||
|
min-width: 250px;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 16px;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 30px;
|
||||||
|
font-size: 17px;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
box-shadow: 0 0 8px 1px #fff;
|
||||||
|
opacity: 0;
|
||||||
|
transition: all 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snackbar.show {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
{
|
||||||
|
"name": "deplacement-covid-19",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Générateur d'attestation de déplacement dérogatoire'",
|
||||||
|
"main": "certificate.js",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint ./*.js",
|
||||||
|
"start": "VERSION=${VERSION:-localversion} parcel index.html robots.txt",
|
||||||
|
"prebuild": "npm run lint && rimraf dist",
|
||||||
|
"build": "PUBLIC_URL=${PUBLIC_URL:-/deplacement-covid-19} ; parcel build --public-url ${PUBLIC_URL} index.html robots.txt",
|
||||||
|
"postbuild": "PUBLIC_URL=${PUBLIC_URL:-/deplacement-covid-19} react-snap"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/lab-mi/deplacement-codiv-19"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/lab-mi/deplacement-covid-19/issues"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.9.0",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.9.0",
|
||||||
|
"babel-eslint": "^10.1.0",
|
||||||
|
"eslint": "^6.8.0",
|
||||||
|
"eslint-config-standard": "^14.1.1",
|
||||||
|
"eslint-plugin-import": "^2.20.1",
|
||||||
|
"eslint-plugin-node": "^11.0.0",
|
||||||
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
|
"eslint-plugin-standard": "^4.0.1",
|
||||||
|
"parcel-bundler": "^1.12.4",
|
||||||
|
"postcss-current-selector": "0.0.3",
|
||||||
|
"postcss-nested": "^4.2.1",
|
||||||
|
"postcss-nested-ancestors": "^2.0.0",
|
||||||
|
"postcss-preset-env": "^6.7.0",
|
||||||
|
"react-snap": "^1.23.0",
|
||||||
|
"rimraf": "^3.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"bootstrap": "^4.4.1",
|
||||||
|
"pdf-lib": "^1.4.1",
|
||||||
|
"qrcode": "^1.4.4"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"last 5 versions"
|
||||||
|
],
|
||||||
|
"reactSnap": {
|
||||||
|
"source": "dist",
|
||||||
|
"minifyHtml": {
|
||||||
|
"collapseWhitespace": false,
|
||||||
|
"removeComments": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
autoprefixer: {
|
||||||
|
grid: true,
|
||||||
|
},
|
||||||
|
'postcss-preset-env': {},
|
||||||
|
'postcss-nested-ancestors': {},
|
||||||
|
'postcss-nested': {},
|
||||||
|
'postcss-current-selector': {},
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
User-agent: *
|