diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml
index 782447567..f1d060325 100644
--- a/.github/workflows/coding-style.yml
+++ b/.github/workflows/coding-style.yml
@@ -37,4 +37,4 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: npm install
- - run: npx eslint src/assets/netteForms.js
+ - run: npx eslint
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 2d1775889..aed90668b 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- php: ['8.1', '8.2', '8.3']
+ php: ['8.1', '8.2', '8.3', '8.4']
fail-fast: false
@@ -65,8 +65,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- - run: npm install -g karma-cli
+ - run: npm install
- working-directory: tests/netteForms
- run: npm install
- - working-directory: tests/netteForms
- run: karma start
+ run: npx karma start karma.conf.cjs
diff --git a/composer.json b/composer.json
index 40c44dace..149e2941a 100644
--- a/composer.json
+++ b/composer.json
@@ -15,7 +15,7 @@
}
],
"require": {
- "php": "8.1 - 8.3",
+ "php": "8.1 - 8.4",
"nette/component-model": "^3.1",
"nette/http": "^3.3",
"nette/utils": "^4.0.4"
@@ -24,12 +24,12 @@
"nette/application": "^3.0",
"nette/di": "^3.0",
"nette/tester": "^2.5.2",
- "latte/latte": "^2.10.2 || ^3.0.12",
+ "latte/latte": "^3.0.12",
"tracy/tracy": "^2.9",
"phpstan/phpstan-nette": "^1"
},
"conflict": {
- "latte/latte": ">=3.0.0 <3.0.12 || >=3.1"
+ "latte/latte": "<3.0.12"
},
"suggest": {
"ext-intl": "to use date/time controls"
@@ -44,7 +44,7 @@
},
"extra": {
"branch-alias": {
- "dev-master": "3.2-dev"
+ "dev-master": "4.0-dev"
}
}
}
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 000000000..d4cc80561
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,48 @@
+import globals from 'globals';
+import pluginJs from '@eslint/js';
+import stylistic from '@stylistic/eslint-plugin';
+
+export default [
+ {
+ ignores: [
+ '*/', '!src/', '!tests/',
+ '**/*.min.js',
+ ],
+ },
+
+ pluginJs.configs.recommended,
+
+ stylistic.configs.customize({
+ indent: 'tab',
+ braceStyle: '1tbs',
+ arrowParens: true,
+ semi: true,
+ jsx: false,
+ }),
+
+ {
+ languageOptions: {
+ ecmaVersion: 2021,
+ globals: {
+ ...globals.browser,
+ ...globals.jasmine,
+ ...globals.amd,
+ ...globals.commonjs,
+ Nette: 'readable',
+ Tracy: 'writeable',
+ },
+ },
+ plugins: {
+ '@stylistic': stylistic,
+ },
+ rules: {
+ '@stylistic/no-multiple-empty-lines': ['error', { max: 2, maxEOF: 0 }],
+ '@stylistic/new-parens': ['error', 'never'],
+ '@stylistic/padded-blocks': 'off',
+ 'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
+ 'prefer-arrow-callback': 'error',
+ 'arrow-body-style': 'error',
+ 'no-var': 'error',
+ },
+ },
+];
diff --git a/eslint.config.mjs b/eslint.config.mjs
deleted file mode 100644
index 3e78d371e..000000000
--- a/eslint.config.mjs
+++ /dev/null
@@ -1,30 +0,0 @@
-import globals from 'globals';
-import pluginJs from '@eslint/js';
-
-export default [
- pluginJs.configs.recommended,
- {
- ignores: ['**/*.min.js'],
- },
- {
- languageOptions: {
- ecmaVersion: 2021,
- globals: {
- ...globals.browser,
- 'Tracy': 'writeable',
- 'define': 'readable',
- 'module': 'readable',
- },
- },
- rules: {
- indent: ['error', 'tab'],
- quotes: ['error', 'single'],
- semi: ['error', 'always'],
- 'func-style': ['error', 'declaration', {'allowArrowFunctions': true}],
- 'prefer-arrow-callback': ['error'],
- 'arrow-parens': ['error'],
- 'arrow-spacing': ['error'],
- 'no-var': ['error'],
- },
- },
-];
diff --git a/package.json b/package.json
index 9a73a127b..17ae86541 100644
--- a/package.json
+++ b/package.json
@@ -1,26 +1,14 @@
{
- "name": "nette-forms",
- "version": "3.4.1",
- "description": "Client side script for Nette Forms Component",
- "keywords": [
- "nette",
- "validation",
- "forms"
- ],
- "homepage": "https://nette.org",
- "author": "David Grudl (https://davidgrudl.com)",
- "license": "BSD-3-Clause",
- "main": "src/assets/netteForms.js",
- "files": [
- "src/assets"
- ],
- "repository": {
- "type": "git",
- "url": "git+https://github.com/nette/forms.git"
- },
+ "type": "module",
"devDependencies": {
- "@eslint/js": "^9.1.1",
- "eslint": "^9.1.1",
- "globals": "^15.1.0"
+ "@eslint/js": "^9.4.0",
+ "@stylistic/eslint-plugin": "^2.1.0",
+ "eslint": "^9.4.0",
+ "globals": "^15.3.0",
+ "jasmine": "^5.1.0",
+ "jasmine-core": "^5.1.1",
+ "karma": "^6.4.2",
+ "karma-chrome-launcher": "^3.2.0",
+ "karma-jasmine": "^5.1.0"
}
}
diff --git a/readme.md b/readme.md
index feca8b09a..45ffe2514 100644
--- a/readme.md
+++ b/readme.md
@@ -2,8 +2,8 @@ Nette Forms: greatly facilitates web forms
==========================================
[![Downloads this Month](https://img.shields.io/packagist/dm/nette/forms.svg)](https://packagist.org/packages/nette/forms)
-[![Tests](https://github.com/nette/forms/actions/workflows/tests.yml/badge.svg?branch=v3.2)](https://github.com/nette/forms/actions)
-[![Coverage Status](https://coveralls.io/repos/github/nette/forms/badge.svg?branch=v3.2)](https://coveralls.io/github/nette/forms?branch=v3.2)
+[![Tests](https://github.com/nette/forms/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/nette/forms/actions)
+[![Coverage Status](https://coveralls.io/repos/github/nette/forms/badge.svg?branch=master)](https://coveralls.io/github/nette/forms?branch=master)
[![Latest Stable Version](https://poser.pugx.org/nette/forms/v/stable)](https://github.com/nette/forms/releases)
[![License](https://img.shields.io/badge/license-New%20BSD-blue.svg)](https://github.com/nette/forms/blob/master/license.md)
@@ -44,7 +44,7 @@ The recommended way to install is via Composer:
composer require nette/forms
```
-It requires PHP version 8.1 and supports PHP up to 8.3.
+It requires PHP version 8.1 and supports PHP up to 8.4.
Client-side support can be installed with npm or yarn:
diff --git a/src/Bridges/FormsLatte/FormMacros.php b/src/Bridges/FormsLatte/FormMacros.php
deleted file mode 100644
index 18c889ad2..000000000
--- a/src/Bridges/FormsLatte/FormMacros.php
+++ /dev/null
@@ -1,330 +0,0 @@
-addMacro('form', [$me, 'macroForm'], 'echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack));');
- $me->addMacro('formContext', [$me, 'macroFormContext'], 'array_pop($this->global->formsStack);');
- $me->addMacro('formContainer', [$me, 'macroFormContainer'], 'array_pop($this->global->formsStack); $formContainer = end($this->global->formsStack)');
- $me->addMacro('label', [$me, 'macroLabel'], [$me, 'macroLabelEnd'], null, self::AUTO_EMPTY);
- $me->addMacro('input', [$me, 'macroInput']);
- $me->addMacro('name', [$me, 'macroName'], [$me, 'macroNameEnd'], [$me, 'macroNameAttr']);
- $me->addMacro('inputError', [$me, 'macroInputError']);
- $me->addMacro('formPrint', [$me, 'macroFormPrint']);
- $me->addMacro('formClassPrint', [$me, 'macroFormPrint']);
- }
-
-
- /********************* macros ****************d*g**/
-
-
- /**
- * {form ...}
- */
- public function macroForm(MacroNode $node, PhpWriter $writer)
- {
- if ($node->modifiers) {
- throw new CompileException('Modifiers are not allowed in ' . $node->getNotation());
- }
-
- if ($node->prefix) {
- throw new CompileException('Did you mean
@@ -89,17 +89,17 @@
@@ -111,9 +111,3 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/tests/Forms.Latte3/expected/forms.php b/tests/Forms.Latte3/expected/forms.php
index d43dfec50..1fea76c4f 100644
--- a/tests/Forms.Latte3/expected/forms.php
+++ b/tests/Forms.Latte3/expected/forms.php
@@ -1,97 +1,96 @@
global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */;
- Nette\Bridges\FormsLatte\Runtime::initializeForm($form);
- echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form, ['id' => 'myForm', 'class' => 'ajax']) /* line %d% */;
+ $this->global->forms->begin($form = $this->global->uiControl['myForm']) /* line %d% */;
+ echo $this->global->forms->renderFormBegin(['id' => 'myForm', 'class' => 'ajax']) /* line %d% */;
echo "\n";
foreach (['id', 'username', 'select', 'area', 'send'] as $name) /* line %d% */ {
echo ' ';
- echo ($ʟ_label = Nette\Bridges\FormsLatte\Runtime::item($name, $this->global)->getLabel()) /* line %d% */;
+ echo ($ʟ_label = $this->global->forms->item($name)->getLabel()) /* line %d% */;
echo '
';
- echo Nette\Bridges\FormsLatte\Runtime::item($name, $this->global)->getControl()->addAttributes(['title' => 'Hello', 'size' => 10]) /* line %d% */;
+ echo $this->global->forms->item($name)->getControl()->addAttributes(['title' => 'Hello', 'size' => 10]) /* line %d% */;
echo '
';
- echo LR\Filters::escapeHtmlText(Nette\Bridges\FormsLatte\Runtime::item($name, $this->global)->getError()) /* line %d% */;
+ echo LR\Filters::escapeHtmlText($this->global->forms->item($name)->getError()) /* line %d% */;
echo '
';
- echo ($ʟ_label = Nette\Bridges\FormsLatte\Runtime::item($form[$name], $this->global)->getLabel())?->addAttributes(['title' => 'hello'])?->startTag() /* line %d% */;
+ echo ($ʟ_label = $this->global->forms->item($form[$name])->getLabel())?->addAttributes(['title' => 'hello'])?->startTag() /* line %d% */;
echo ' ';
- echo Nette\Bridges\FormsLatte\Runtime::item($form[$name], $this->global)->getControl()->addAttributes(['title' => 'Hello', 'size' => 10]) /* line %d% */;
+ echo $this->global->forms->item($form[$name])->getControl()->addAttributes(['title' => 'Hello', 'size' => 10]) /* line %d% */;
echo ' ';
echo $ʟ_label?->endTag() /* line %d% */;
echo '
';
- echo LR\Filters::escapeHtmlText(Nette\Bridges\FormsLatte\Runtime::item($form[$name], $this->global)->getError()) /* line %d% */;
+ echo LR\Filters::escapeHtmlText($this->global->forms->item($form[$name])->getError()) /* line %d% */;
echo "\n";
}
echo '
';
- echo ($ʟ_label = Nette\Bridges\FormsLatte\Runtime::item($form['username'], $this->global)->getLabel()) /* line %d% */;
+ echo ($ʟ_label = $this->global->forms->item($form['username'])->getLabel()) /* line %d% */;
echo '
global)->getControlPart())->addAttributes(['value' => null, 'type' => null, 'class' => null])->attributes() /* line %d% */;
+ echo ($ʟ_elem = $this->global->forms->item('username')->getControlPart())->addAttributes(['value' => null, 'type' => null, 'class' => null])->attributes() /* line %d% */;
echo '>
global)->getControlPart())->attributes() /* line %d% */;
+ echo ($ʟ_elem = $this->global->forms->item($form['username'])->getControlPart())->attributes() /* line %d% */;
echo '>
';
- echo ($ʟ_label = Nette\Bridges\FormsLatte\Runtime::item('my', $this->global)->getLabel()) /* line %d% */;
- echo Nette\Bridges\FormsLatte\Runtime::item('my', $this->global)->getControl() /* line %d% */;
+ echo ($ʟ_label = $this->global->forms->item('my')->getLabel()) /* line %d% */;
+ echo $this->global->forms->item('my')->getControl() /* line %d% */;
echo "\n";
- echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack)) /* line %d% */;
+ echo $this->global->forms->renderFormEnd() /* line %d% */;
+ $this->global->forms->end();
echo '
';
- $form = $this->global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */;
- Nette\Bridges\FormsLatte\Runtime::initializeForm($form);
- echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form, []) /* line %d% */;
- echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack)) /* line %d% */;
+ $this->global->forms->begin($form = $this->global->uiControl['myForm']) /* line %d% */;
+ echo $this->global->forms->renderFormBegin([]) /* line %d% */;
+ echo $this->global->forms->renderFormEnd() /* line %d% */;
+ $this->global->forms->end();
echo '
';
- $form = $this->global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */;
- Nette\Bridges\FormsLatte\Runtime::initializeForm($form);
- echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form, []) /* line %d% */;
+ $this->global->forms->begin($form = $this->global->uiControl['myForm']) /* line %d% */;
+ echo $this->global->forms->renderFormBegin([]) /* line %d% */;
echo "\n";
foreach ($form['sex']->items as $key => $label) /* line %d% */ {
echo ' ';
- echo ($ʟ_label = Nette\Bridges\FormsLatte\Runtime::item('sex', $this->global)->getLabelPart($key))?->startTag() /* line %d% */;
+ echo ($ʟ_label = $this->global->forms->item('sex')->getLabelPart($key))?->startTag() /* line %d% */;
echo ' ';
- echo Nette\Bridges\FormsLatte\Runtime::item('sex', $this->global)->getControlPart($key) /* line %d% */;
+ echo $this->global->forms->item('sex')->getControlPart($key) /* line %d% */;
echo ' ';
echo LR\Filters::escapeHtmlText($label) /* line %d% */;
echo $ʟ_label?->endTag() /* line %d% */;
echo '
@@ -100,47 +99,47 @@
}
echo '
global)->getControlPart("{$key}"))->attributes() /* line %d% */;
+ echo ($ʟ_elem = $this->global->forms->item($form['sex'])->getControlPart("{$key}"))->attributes() /* line %d% */;
echo '>
';
- echo ($ʟ_label = Nette\Bridges\FormsLatte\Runtime::item('checkbox', $this->global)->getLabelPart(''))?->startTag() /* line %d% */;
+ echo ($ʟ_label = $this->global->forms->item('checkbox')->getLabelPart(''))?->startTag() /* line %d% */;
echo ' ';
- echo Nette\Bridges\FormsLatte\Runtime::item('checkbox', $this->global)->getControlPart('') /* line %d% */;
+ echo $this->global->forms->item('checkbox')->getControlPart('') /* line %d% */;
echo ' Label';
echo $ʟ_label?->endTag() /* line %d% */;
echo '
@@ -149,20 +148,20 @@
';
foreach ($form['checklist']->items as $key => $label) /* line %d% */ {
echo ' ';
- echo ($ʟ_label = Nette\Bridges\FormsLatte\Runtime::item('checklist', $this->global)->getLabelPart($key))?->startTag() /* line %d% */;
+ echo ($ʟ_label = $this->global->forms->item('checklist')->getLabelPart($key))?->startTag() /* line %d% */;
echo ' ';
- echo Nette\Bridges\FormsLatte\Runtime::item('checklist', $this->global)->getControlPart($key) /* line %d% */;
+ echo $this->global->forms->item('checklist')->getControlPart($key) /* line %d% */;
echo ' ';
echo LR\Filters::escapeHtmlText($label) /* line %d% */;
echo $ʟ_label?->endTag() /* line %d% */;
echo '
@@ -171,15 +170,15 @@
}
echo '
@@ -187,65 +186,62 @@
';
if (1) /* line %d% */ {
- $form = $this->global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */;
- Nette\Bridges\FormsLatte\Runtime::initializeForm($form);
+ $this->global->forms->begin($form = $this->global->uiControl['myForm']) /* line %d% */;
echo '
';
- array_pop($this->global->formsStack);
+ $this->global->forms->end();
}
echo '
';
- $form = $this->global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */;
- Nette\Bridges\FormsLatte\Runtime::initializeForm($form);
+ $this->global->forms->begin($form = $this->global->uiControl['myForm']) /* line %d% */;
echo '
';
- array_pop($this->global->formsStack);
+ $this->global->forms->end();
echo '
';
- $form = $this->global->formsStack[] = is_object($ʟ_tmp = $this->global->uiControl['myForm']) ? $ʟ_tmp : $this->global->uiControl[$ʟ_tmp] /* line %d% */;
- Nette\Bridges\FormsLatte\Runtime::initializeForm($form);
+ $this->global->forms->begin($form = (is_object($ʟ_tmp = $this->global->uiControl['myForm']) ? $ʟ_tmp : $this->global->uiControl[$ʟ_tmp])) /* line %d% */;
echo '
';
- array_pop($this->global->formsStack);
+ $this->global->forms->end();
echo '