li + li {}
Выбирает все элементы кроме первого.li:last-child {}
Выбирает только последний элемент.li:not(:first-child) {}
div > (a + p + p + p)
p + p
выберет последние два параграфаp:not(:first-child)
- все параграфы. {
"private": true,
"scripts": {
"site:development": "mix",
"site:watch": "mix watch",
"site:hot": "mix watch --hot",
"site:production": "mix --production",
"dashboard:watch": "cross-env TARGET=dashboard mix watch",
"dashboard:hot": "cross-env TARGET=dashboard mix watch --hot",
"dashboard:production": "cross-env TARGET=dashboard mix --production"
},
"devDependencies": {
"browser-sync": "^2.26.14",
"browser-sync-webpack-plugin": "^2.2.2",
"chalk": "^4.1.0",
"cross-env": "^7.0.3",
"dotenv": "^8.2.0",
"laravel-mix": "^6.0.13",
"resolve-url-loader": "^3.1.2",
"sass": "^1.32.8",
"sass-loader": "^10.1.1"
},
"dependencies": {}
}
/** @type {Api} */
const mix = require('laravel-mix');
const path = require('path');
const dotenv = require('dotenv');
/** @type {Chalk} */
const chalk = require('chalk');
const dotEnvLocation = path.resolve('./.env');
dotenv.config({ path: dotEnvLocation });
const WATCH = process.argv.includes('--watch');
const HOT = process.argv.includes('--hot');
const localDomain = process.env.LOCAL_DOMAIN ?? 'localhost';
const target = process.env.TARGET ?? 'site';
let browserSyncPort = 3000;
let hmrPort = 8088;
const logs = {
mode : WATCH ? chalk.red('WATCH') : HOT ? chalk.red('HOT') : 'None',
domain : process.env.LOCAL_DOMAIN ?? chalk.red(localDomain),
frontend: process.env.FRONTEND_DIST ?? chalk.red(process.env.FRONTEND_DIST),
backend : process.env.BACKEND_DIST ?? chalk.red(process.env.BACKEND_DIST),
};
console.log(chalk.cyan('Local domain: ') + logs.domain);
console.log(chalk.cyan('Location .env: ') + dotEnvLocation);
console.log(chalk.cyan('Mode: ') + logs.mode);
console.log(chalk.cyan('Public paths:'));
console.log(chalk.cyan(' Frontend: ') + logs.frontend);
console.log(chalk.cyan(' Backend: ') + logs.backend);
if (target === 'dashboard') {
browserSyncPort = process.env.BACKEND_LOCAL_PORT ?? 3000;
hmrPort = process.env.BACKEND_HMR_PORT ?? 8088;
require('./webpack-dashboard.mix.js');
}
if (target === 'site') {
browserSyncPort = process.env.FRONTEND_LOCAL_PORT ?? 3001;
hmrPort = process.env.FRONTEND_HMR_PORT ?? 8089;
require('./webpack-site.mix.js');
}
/*==
*== Customize options
*== ======================================= ==*/
mix.version();
mix.disableSuccessNotifications();
if (!HOT && WATCH) {
mix.browserSync({
proxy : localDomain,
startPath: target === 'site' ? '/' : '/admin',
browser : ['chrome'],
notify : false,
port : browserSyncPort,
});
}
mix.options({
clearConsole: false,
hmrOptions : {
host: 'localhost',
port: hmrPort,
},
});
const webpackResolveRules = {
extensions: ['*', '.wasm', '.mjs', '.js', '.jsx', '.json', '.vue'],
alias : {
'@': path.join(__dirname, 'resources/js'),
},
};
mix.sourceMaps(false, 'source-map');
if (!mix.inProduction()) {
mix.webpackConfig({
output : { devtoolModuleFilenameTemplate: '[resource-path]' },
resolve: webpackResolveRules,
});
} else {
mix.webpackConfig({
resolve: webpackResolveRules,
});
}
/** @type {Api} */
const mix = require('laravel-mix');
const HOT = process.argv.includes('--hot');
if (!process.env.FRONTEND_DIST) throw Error;
mix.setPublicPath(`public/${process.env.FRONTEND_DIST}`);
if (!HOT) mix.setResourceRoot(`/${process.env.FRONTEND_DIST}`);
mix.js('resources/js/app.js', 'js');
mix.sass('resources/scss/app.scss', 'css');
mix.extract();
/** @type {Api} */
const mix = require('laravel-mix');
const HOT = process.argv.includes('--hot');
if (!process.env.BACKEND_DIST) throw Error;
mix.setPublicPath(`public/${process.env.BACKEND_DIST}`);
if (!HOT) mix.setResourceRoot(`/${process.env.BACKEND_DIST}`);
mix.js('resources/dashboard/js/main.js', 'js');
mix.sass('resources/dashboard/scss/main.scss', 'css');
mix.extract();
LOCAL_DOMAIN=delphinpro.local
FRONTEND_LOCAL_PORT=3000
FRONTEND_HMR_PORT=8003
FRONTEND_DIST=dist/frontend
BACKEND_LOCAL_PORT=3004
BACKEND_HMR_PORT=8004
BACKEND_DIST=dist/backend
<?php
return [
// .....
'frontend' => [
'dist' => env('FRONTEND_DIST'),
],
'backend' => [
'dist' => env('BACKEND_DIST'),
],
];
<link href="{{ mix('css/app.css', config('app.frontend.dist')) }}" rel="stylesheet">
<script src="{{ mix('js/app.js', config('app.frontend.dist')) }}"></script>
$font-size-base: 12px
$line-height-base: 16px
text-margin($top, $right, $bottom, $left, $font-size: $font-size-base, $line-height: $line-height-base)
if $top != 0
$top: $top - ($line-height - $font-size) / 2
if $bottom != 0
$bottom: $bottom - ($line-height - $font-size) / 2
margin: $top $right $bottom $left
@mixin text-margin($top, $right, $bottom, $left, $font-size: $font-size-base, $line-height: $line-height-base) {
}
<div id="calculator"></div>
export function mountVueComponent(targetId, component) {
if (document.getElementById(targetId)) {
new (Vue.extend(component))().$mount(`#${targetId}`);
}
}
import Calculator from '....';
mountVueComponent('calculator', Calculator);
<div class="mini-calc"></div>
Array.from(document.querySelectorAll('.mini-calc')).forEach(el => {
let yandexGoal = el.dataset['goal'];
new Vue({
el : el,
render: createElement => createElement(Calculator, {
props: {
displayAs: CALC_DISPLAY_AS_MINI,
yandexGoal,
},
}),
});
});
пароль htmlspecialchars для перестраховки
минимальную фильтрацию где это необходимо
разрешить в логин и имя только a-zа-яё0-9