├── .github └── ISSUE_TEMPLATE │ ├── config.yml │ ├── bugreport.yml │ └── new-rule.yml ├── assets ├── logo.png ├── vs-code-report.png └── logo.svg ├── .gitignore ├── package.json ├── LICENSE ├── README.md ├── index.js ├── CHANGELOG.md └── test ├── catalog.html └── index.html /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/htmlacademy/linthtml-config-htmlacademy/HEAD/assets/logo.png -------------------------------------------------------------------------------- /assets/vs-code-report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/htmlacademy/linthtml-config-htmlacademy/HEAD/assets/vs-code-report.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | yarn.lock 3 | .DS_Store 4 | Thumbs.db 5 | .idea 6 | *.sublime* 7 | .idea/ 8 | *.lock 9 | .publish 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "linthtml-config-htmlacademy", 3 | "version": "1.1.0", 4 | "description": "HTML Academy LintHTML config", 5 | "main": "index.js", 6 | "scripts": { 7 | "lint": "linthtml test/*.html --config index.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/htmlacademy/linthtml-config-htmlacademy.git" 12 | }, 13 | "keywords": [], 14 | "author": "Nikolai Shabalin", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/htmlacademy/linthtml-config-htmlacademy/issues" 18 | }, 19 | "homepage": "https://github.com/htmlacademy/linthtml-config-htmlacademy#readme", 20 | "dependencies": { 21 | "@linthtml/linthtml": "0.10.1", 22 | "linthtml-rules-htmlacademy": "1.1.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 HTML Academy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bugreport.yml: -------------------------------------------------------------------------------- 1 | name: 'Сообщение о проблеме' 2 | description: 'Issue для сообщения о проблеме или баге' 3 | title: 'Проблема: ' 4 | labels: ['bug'] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Спасибо, что помогаете улучшить наш проект! Пожалуйста, заполните следующую информацию: 10 | 11 | - type: textarea 12 | id: terminal-error 13 | attributes: 14 | label: Ошибка из терминала 15 | description: | 16 | ```bash 17 | File: test/index.html 18 | Config file: index.js 19 | 8:3 error The
element must contain a heading of any level. htmlacademy/section-has-heading 20 | ✖ 1 problem (1 error, 0 warning) 21 | ``` 22 | - type: textarea 23 | id: example 24 | attributes: 25 | label: Часть кода на котором произошла ошибка. Какая конфигурация использовалась 26 | description: | 27 | ```html 28 |
29 |

Title

30 |
31 | ``` 32 | 33 | - type: textarea 34 | id: description 35 | attributes: 36 | label: Описание проблемы 37 | description: Пожалуйста, подробно опишите проблему или баг. Опишите как воспроизвести баг 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new-rule.yml: -------------------------------------------------------------------------------- 1 | name: 'Новое правило' 2 | description: 'Issue для предложения нового правила в линтер' 3 | title: 'Правило: ' 4 | labels: ["enhancement"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Спасибо, что нашли временем поделиться новым правилом 10 | 11 | - type: textarea 12 | id: description 13 | attributes: 14 | label: Опишите коротко, что будет проверять правило своими словами 15 | description: Проверяет наличие заголовка любого уровня в `
`. 16 | 17 | - type: textarea 18 | id: bad-example 19 | attributes: 20 | label: Напишите примеры кода, на которые правило должно выдавать ошибку 21 | description: | 22 | Без заголовка 23 | ```html 24 |
25 |
26 | ``` 27 | 28 | - type: textarea 29 | id: good-example 30 | attributes: 31 | label: Напишите примеры кода, на которые правило не должно реагировать 32 | description: | 33 | C заголовком 34 | ```html 35 |
36 |

37 |
38 | ``` 39 | 40 | С любой вложенностью 41 | ```html 42 |
43 |
44 |

45 |
46 |
47 | ``` 48 | 49 | - type: textarea 50 | id: free 51 | attributes: 52 | label: Поле со свободным описанием. 53 | description: Добавьте сюда всё остальное, что хотели рассказать 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | logo linthtml-config-htmlacademy 3 |
4 | 5 | # linthtml-config-htmlacademy 6 | > Это стандартный конфигурационный файл для linthtml от [HTML Academy](https://htmlacademy.ru/). 7 | 8 | ## Установка 9 | 10 | ```bash 11 | npm install @linthtml/linthtml linthtml-config-htmlacademy -D 12 | ``` 13 | 14 | ## Использование 15 | 16 | Когда вы установили `linthtml-config-htmlacademy` локально в свой проект, примените его в конфигурационном файле `.linthtmlrc` вашего проекта: 17 | 18 | ```json 19 | { 20 | "extends": "linthtml-config-htmlacademy" 21 | } 22 | ``` 23 | 24 | ### Расширение конфига 25 | 26 | Просто добавьте ключ `"rules"` в ваш конфиг после `"extends": "linthtml-config-htmlacademy"`, а затем добавьте туда свои правила. 27 | 28 | Например, если вы хотите изменить максимальную длину `line-max-len`, то нужно: 29 | 30 | ```json 31 | { 32 | "extends": "linthtml-config-htmlacademy", 33 | "rules": { 34 | "line-max-len": [ 35 | true, 36 | 120 37 | ] 38 | } 39 | } 40 | ``` 41 | 42 | ## Правила 43 | Для проекта добавляются кастомные правила от [HTML Academy](https://htmlacademy.ru/), которые лежат в отдельном репозитории [linthtml-rules-htmlacademy](https://github.com/htmlacademy/linthtml-rules-htmlacademy). 44 | 45 | ## Использование в VS Code 46 | Чтобы VS Code начал подсвечивать ошибки в HTML-разметке, установите плагин [LintHTML](https://marketplace.visualstudio.com/items?itemName=kamikillerto.vscode-linthtml). 47 | 48 | > Обязательно убедитесь, что файл настроек называется `.linthtmlrc`, так как это обязательное [требование плагина](https://marketplace.visualstudio.com/items?itemName=kamikillerto.vscode-linthtml#:~:text=If%20you%20have%20a%20valid%20hmllint%20configuration%20file). 49 | 50 | ![](assets/vs-code-report.png) 51 | 52 | ## npm и cli 53 | Linthtml можно запускать в терминале. Для этого можно в секцию `"script"` в `package.json` добавить команду: 54 | ```bash 55 | # package.json 56 | "script" { 57 | "lint:html": "linthtml source/*.html --config .linthtmlrc" 58 | } 59 | ``` 60 | 61 | - `linthtml` - запустит проверку HTML-файлов. 62 | - `source/*.html` - поиск HTML-файлов в папке `source`. 63 | - `--config .linthtmlrc` - путь до конфигурационного файла. В проекте можно иметь несколько конфигурационных файлов. 64 | -------------------------------------------------------------------------------- /assets/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'id-class-ignore-regex': false, 3 | 'line-max-len-ignore-regex': false, 4 | 'spec-char-escape': false, 5 | 'plugins': ['linthtml-rules-htmlacademy'], 6 | 'attr-name-ignore-regex': 'viewBox|preserveAspectRatio', 7 | 'rules': { 8 | 'htmlacademy/space-between-comments': [true, 'space'], 9 | 'htmlacademy/a-target-rel': true, 10 | 'htmlacademy/aria-label-misuse': true, 11 | 'htmlacademy/attr-delimiter': true, 12 | 'htmlacademy/attr-req-value': [true, { ignore: ['alt'] }], 13 | 'htmlacademy/attribute-allowed-values': [ 14 | true, { 15 | 'input': { 16 | attributes: { 17 | 'type': { 18 | enum: [ 19 | 'text', 'email', 'password', 'radio', 'checkbox', 'file', 'number', 'color', 20 | 'date', 'range', 'hidden' 21 | ], 22 | }, 23 | }, 24 | }, 25 | }, 26 | ], 27 | 'htmlacademy/ban-url-spaces': true, 28 | 'htmlacademy/charset-position': true, 29 | 'htmlacademy/class-first': true, 30 | 'htmlacademy/form-action-attribute': true, 31 | 'htmlacademy/head-meta-charset': true, 32 | 'htmlacademy/id-no-dup': true, 33 | 'htmlacademy/img-svg-req-dimensions': true, 34 | 'htmlacademy/input-req-label': true, 35 | 'htmlacademy/link-req-content': true, 36 | 'htmlacademy/no-blocking-script': true, 37 | 'htmlacademy/no-double-br': true, 38 | 'htmlacademy/no-px-size': true, 39 | 'htmlacademy/req-charset-utf': true, 40 | 'htmlacademy/req-head-styles': true, 41 | 'htmlacademy/req-mailto': true, 42 | 'htmlacademy/req-meta-viewport': true, 43 | 'htmlacademy/req-single-styles': true, 44 | 'htmlacademy/req-stylesheet-link': true, 45 | 'htmlacademy/section-has-heading': true, 46 | 'htmlacademy/tag-name-lowercase': [true, { 47 | ignore: ['clipPath', 'textPath', 'linearGradient', 'radialGradient'] 48 | }], 49 | 'htmlacademy/tag-req-attr': [ 50 | true, { 51 | 'input': [ 52 | { 53 | name: 'name', 54 | ignore: { 55 | type: 'submit' 56 | } 57 | }, 58 | ], 59 | 'select': [ 60 | { 61 | name: 'name', 62 | }, 63 | ], 64 | 'textarea': [ 65 | { 66 | name: 'name', 67 | }, 68 | ], 69 | 'time': [ 70 | { 71 | name: 'datetime', 72 | }, 73 | ], 74 | 'source': [ 75 | { 76 | name: 'type', 77 | }, 78 | ], 79 | 'button': [ 80 | { 81 | name: 'type', 82 | }, 83 | ], 84 | 'a': [ 85 | { 86 | name: 'href', 87 | }, 88 | ], 89 | }, 90 | ], 91 | 'htmlacademy/tag-self-close': true, 92 | 'htmlacademy/req-source-width-height': true, 93 | 'htmlacademy/tag-forbid-attr': false, 94 | 'htmlacademy/req-tags-presence': [true, ['h1', 'main']], 95 | 'htmlacademy/req-preload-font': true, 96 | 'htmlacademy/req-webp-in-picture': true, 97 | 'htmlacademy/no-class-in-container': false, 98 | 99 | 'attr-bans': false, 100 | 'attr-name-style': [true, 'dash'], 101 | 'attr-new-line': false, 102 | 'attr-no-dup': true, 103 | 'attr-no-unsafe-char': true, 104 | 'attr-order': false, 105 | 'attr-quote-style': [true, 'double'], 106 | 'attr-req-value': false, 107 | 'attr-validate': true, 108 | 'button-req-content': true, 109 | 'class-no-dup': true, 110 | 'class-style': false, 111 | 'doctype-first': true, 112 | 'doctype-html5': true, 113 | 'fieldset-contains-legend': true, 114 | 'fig-req-figcaption': true, 115 | 'focusable-tabindex-style': true, 116 | 'head-req-title': true, 117 | 'head-valid-content-model': true, 118 | 'href-style': false, 119 | 'html-req-lang': true, 120 | 'html-valid-content-model': true, 121 | 'id-class-no-ad': false, 122 | 'id-class-style': false, 123 | 'id-no-dup': false, // fixme правило сломано в последней версии линтера ждем https://github.com/linthtml/linthtml/issues/469 124 | 'id-style': [true, 'dash'], 125 | 'img-req-alt': [true, 'allownull'], 126 | 'img-req-src': true, 127 | 'indent-style': false, 128 | 'indent-width': false, 129 | 'input-btn-req-value-or-title': true, 130 | 'input-radio-req-name': true, 131 | 'input-req-label': false, 132 | 'label-no-enc-textarea-or-select': true, 133 | 'label-req-for': false, 134 | 'lang-style': [true, 'case'], 135 | 'line-end-style': false, 136 | 'line-max-len': false, 137 | 'line-no-trailing-whitespace': false, 138 | 'no-surrounding-whitespace': true, 139 | 'link-min-length-4': false, 140 | 'spec-char-escape': false, 141 | 'link-req-noopener': false, 142 | 'table-req-caption': false, 143 | 'table-req-header': false, 144 | 'tag-bans': [true, 'style'], 145 | 'tag-close': true, 146 | 'tag-name-lowercase': false, 147 | 'tag-name-match': true, 148 | 'tag-self-close': false, 149 | 'title-max-len': false, 150 | 'title-no-dup': true, 151 | }, 152 | }; 153 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.0.25 4 | Fixes `req-webp-in-picture` to not check `` if all `` have attribute `type="image/svg+xml"`. 5 | 6 | ## 1.0.24 7 | - Adds a `req-tags-presence` rule that requires the specified tags on the page. 8 | - Adds a `req-preload-font` rule that requires the `preload` value for the font. 9 | - Adds a `req-webp-in-picture` rule that requires `webp` in `` 10 | - Adds a `no-class-in-container` rule that checks the `class` attribute for child elements inside the specified container. 11 | 12 | ```json 13 | { 14 | "htmlacademy/req-tags-presence": [ true, ["header", "nav", "main", "section", "h1", "footer"]], 15 | "htmlacademy/req-preload-font": true, 16 | "htmlacademy/req-webp-in-picture": true, 17 | "htmlacademy/no-class-in-container": [true, { 18 | "containers": ["content"], 19 | "ignore": { 20 | "tags": ["h1", "p"], 21 | "classes": ["content__title"] 22 | } 23 | }] 24 | } 25 | ``` 26 | 27 | ## 1.0.23 28 | Update dependencies. Adds a `tag-forbid-attr` rule that disallows the use of specified attributes on the specified tag. 29 | 30 | ## 1.0.22 31 | Added a new rule [htmlacademy/req-source-width-height](https://github.com/htmlacademy/linthtml-rules-htmlacademy/blob/main/rules/req-source-width-height/README.md) that requires the `width` and `height` attributes of ``, inside ``. 32 | 33 | ```html 34 | 35 | 36 | 37 | 38 | ``` 39 | 40 | ## 1.0.21 41 | Clarifies the [no-blocking-script](rules/no-blocking-script/README.md) rule for the ` 47 | 48 | … 49 | 50 | ``` 51 | 52 | ## 1.0.20 53 | Updates the @linthtml/linthtml to the latest version 54 | 55 | ## 1.0.19 56 | Added a new rule [htmlacademy/req-mailto](https://github.com/htmlacademy/linthtml-rules-htmlacademy/blob/main/rules/req-mailto/README.md), which requires `mailto:` for email-text links. 57 | ```json 58 | { 59 | "htmlacademy/req-mailto": true 60 | } 61 | ``` 62 | 63 | ```html 64 | example@example.com 65 | ``` 66 | 67 | 68 | ## 1.0.18 69 | Added a new rule [htmlacademy/req-stylesheet-link](https://github.com/htmlacademy/linthtml-rules-htmlacademy/blob/main/rules/req-stylesheet-link/README.md) that checks for a link tag with the `rel="stylesheet"` attribute inside the head tag. 70 | ```json 71 | { 72 | "htmlacademy/req-stylesheet-link": true 73 | } 74 | ``` 75 | 76 | ```html 77 | 78 | 79 | 80 | ``` 81 | 82 | ## 1.0.17 83 | - Excludes the `` check from the [input-req-label](rules/input-req-label/README.md) rule. 84 | - Adds `ignore` option for [tag-req-attr](rules/tag-req-attr/README.md) 85 | ```js 86 | 'input': [ 87 | { 88 | name: 'name', 89 | ignore: { 90 | 'type': 'submit' 91 | } 92 | }, 93 | ], 94 | ``` 95 | 96 | ## 1.0.16 97 | Fix `htmlacademy/attr-req-value` rule 98 | 99 | ### Exceptions 100 | A single ` 108 | 109 | 110 | 111 | ``` 112 | 113 | ## 1.0.15 114 | Added `htmlacademy/space-between-comments` 115 | ```js 116 | rules: { 117 | 'htmlacademy/space-between-comments': [true, 'space' | 'no-space] 118 | } 119 | ``` 120 | 121 | This rule checks for spaces at the beginning and end of the comment block. 122 | 123 | ## Options 124 | 125 | `string`: `"space"|"no-space"` 126 | 127 | ## Value `space` 128 | If a comment has spaces at both the beginning and end of the comment block, it is compliant. 129 | 130 | The following patterns are considered problematic: 131 | ```html 132 | 133 | 134 | 135 | ``` 136 | 137 | The following patterns are **not** considered problems: 138 | ```html 139 | 140 | ``` 141 | 142 | ## Value `no-space` 143 | If a comment has **no** spaces at both the beginning and end of the comment block, it is compliant. 144 | 145 | The following patterns are considered problematic: 146 | ```html 147 | 148 | 149 | 150 | ``` 151 | 152 | The following patterns are **not** considered problems: 153 | ```html 154 | 155 | ``` 156 | 157 | ## 1.0.14 158 | `attr-req-value` can now accept regex for ignore 159 | 160 | ```js 161 | 'htmlacademy/attr-req-value': [ 162 | true, 163 | { 164 | ignore: ['/^data/'] 165 | } 166 | ], 167 | ``` 168 | 169 | ## 1.0.13 170 | Disabled `attr-new-line` rule 171 | 172 | ## 1.0.12 173 | Fixed regex in `attr-name-ignore-regex` 174 | 175 | ## 1.0.11 176 | Disabled `link-min-length-4` 177 | 178 | This rule triggered for a good example 179 | ```html 180 | 183 | ``` 184 | 185 | ## 1.0.10 186 | Fixed `req-charset-utf` rule 187 | 188 | ## 1.0.9 189 | - Update linthtml-rules-htmlacademy 190 | - Sorted htmlacademy rules 191 | - Added so many new rules: 192 | - `htmlacademy/attr-req-value` 193 | - `htmlacademy/aria-label-misuse` 194 | - `htmlacademy/attr-delimiter` 195 | - `htmlacademy/attribute-allowed-values` 196 | - `htmlacademy/ban-url-spaces` 197 | - `htmlacademy/id-no-dup` 198 | - `htmlacademy/input-req-label` 199 | - `htmlacademy/link-req-content` 200 | - `htmlacademy/no-blocking-script` 201 | - `htmlacademy/no-px-size` 202 | - `htmlacademy/req-head-styles` 203 | - `htmlacademy/req-meta-viewport` 204 | - `htmlacademy/req-single-styles` 205 | - `htmlacademy/tag-name-lowercase` 206 | - `htmlacademy/tag-self-close` 207 | - Disabled rules: 208 | - `'class-style'` 209 | - `'spec-char-escape'` 210 | - `tag-self-close` 211 | - `input-req-label` 212 | - Enabled rules: 213 | - `'id-style' : [true, 'dash'],` 214 | - `'input-req-label'` 215 | - `'label-no-enc-textarea-or-select'` 216 | - `'no-surrounding-whitespace'` 217 | - `'link-min-length-4'` 218 | - `'tag-self-close' : [true, 'never']` 219 | - Adds: 220 | ```js 221 | { 222 | 'tag-req-attr': [ 223 | true, 224 | { 225 | 'input': [ 226 | { 227 | name: 'name' 228 | }, 229 | ], 230 | 'select': [ 231 | { 232 | name: 'name' 233 | }, 234 | ], 235 | 'textarea': [ 236 | { 237 | name: 'name' 238 | }, 239 | ], 240 | 'time': [ 241 | { 242 | name: 'datetime' 243 | }, 244 | ], 245 | 'source': [ 246 | { 247 | name: 'type' 248 | }, 249 | ], 250 | 'button': [ 251 | { 252 | name: 'type' 253 | }, 254 | ], 255 | 'a': [ 256 | { 257 | name: 'href' 258 | }, 259 | ], 260 | } 261 | ] 262 | } 263 | ``` 264 | 265 | ## 1.0.8 266 | - Update linthtml-rules-htmlacademy 267 | - Adds new rule `htmlacademy/section-has-heading` 268 | ```html 269 |
270 |

title

271 |
272 | 273 |
274 |
275 |

title

276 |
277 |
278 | ``` 279 | 280 | ## 1.0.7 281 | - Update linthtml-rules-htmlacademy 282 | - Adds htmlacademy rules 283 | - Remove bem for id 284 | - Remove `indent-style` 285 | - Remove `line-no-trailing-whitespace` 286 | - Remove `link-req-noopener` 287 | - Adds `spec-char-escape` 288 | - Fixed `head-meta-charset` 289 | 290 | ## 1.0.6 291 | - обновили linthtml-rules-htmlacademy 1.0.2 292 | - удалили `htmlacademy/attr-value-style` 293 | 294 | ## 1.0.5 295 | - Обновили зависимости до актуальных версий 296 | - Добавили linthtml-rules-htmlacademy 297 | 298 | ## 1.0.3 299 | Обновляет зависимости 300 | 301 | ## 1.0.2 302 | Разрешили использовать незаполненный `alt="""` 303 | 304 | ## 1.0.1 305 | - Обновили правила до linthtml@0.7.2 306 | 307 | Новые правила: 308 | - Требуем у `` указывать 4 атрибута 309 | ```json 310 | { 311 | "tag-req-attr": [true, { 312 | "img": [ 313 | {"name": "src"}, 314 | {"name": "alt"}, 315 | {"name": "width"}, 316 | {"name": "height"} 317 | ]} 318 | ] 319 | } 320 | ``` 321 | - Убрали требование писать по БЭМ, так как БЭМ может быть слишком разным 322 | 323 | 324 | ## 1.0.0 325 | - Добавили страницы для тестов и сами тесты 326 | - Добавили правила для linthtml@0.6.0 327 | -------------------------------------------------------------------------------- /test/catalog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | HTML Academy: Девайс. Каталог 7 | 8 | 9 | 10 | 11 |
12 |
13 | 72 |
73 |
74 | 75 |
76 |
77 |

Моноподы для селфи

78 | 79 | 90 |
91 | 92 | 93 |
94 |
95 |
96 |

Фильтр:

97 |
98 | 99 |
100 | 101 |
102 | Стоимость 103 |
104 |
105 |
106 | 107 | 108 |
109 | 110 |
111 | 115 | 116 | 120 |
121 |
122 |
123 | 124 | 125 |
126 | Цвет 127 |
    128 |
  • 129 | 130 | 131 |
  • 132 |
  • 133 | 134 | 135 |
  • 136 |
  • 137 | 138 | 139 |
  • 140 |
  • 141 | 142 | 143 |
  • 144 |
  • 145 | 146 | 147 |
  • 148 |
149 |
150 | 151 | 152 |
153 | Bluetooth 154 |
    155 |
  • 156 | 157 | 158 |
  • 159 |
  • 160 | 161 | 162 |
  • 163 |
164 |
165 | 166 | 167 |
168 |
169 | 170 |
171 |
172 |

Сортировка:

173 | 174 | 185 | 186 |
    187 |
  • 188 | 189 |
  • 190 |
  • 191 | 192 |
  • 193 |
194 |
195 | 196 |
197 | 247 |
248 | 249 |
250 |
    251 |
  • 252 | Назад 253 |
  • 254 |
  • 255 | 1 256 |
  • 257 |
  • 258 | 2 259 |
  • 260 |
  • 261 | 3 262 |
  • 263 |
  • 264 | Вперед 265 |
  • 266 |
267 |
268 |
269 |
270 | 271 |
272 | 273 | 345 | 346 | 347 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HTML Academy: Девайс 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 72 |
73 |
74 | 75 |
76 |
77 |

Интернет-магазин гаджетов "Девайс"

78 |
79 |

Новинки

80 | 81 |
82 | 83 |
    84 |
  • 85 | 86 |
  • 87 |
  • 88 | 89 |
  • 90 |
  • 91 | 92 |
  • 93 |
94 | 95 |
    96 |
  1. 97 |
    98 | телескопическая селфи-палка 99 |
    100 |
    101 | 01 102 |

    Делай селфи,
    как Бен Стиллер!

    103 |

    Самая длинная палка для селфи доступна в нашем магазине.
    Восемь (Восемь, Карл!) метров длиной и весом всего 5 килограмм.

    104 | Подробнее 105 | 106 |
      107 |
    • 108 | 8,5 м 109 | Длина палки 110 |
    • 111 |
    • 112 | 5 кг 113 | Вес палки 114 |
    • 115 |
    • 116 | Карбон 117 | Материал 118 |
    • 119 |
    120 |
    121 |
  2. 122 | 123 |
  3. 124 |
    125 | фитнес-браслет 126 |
    127 |
    128 | 02 129 |

    Худеем
    правильно!

    130 |

    Мотивирующие фитнес-браслеты помогут найти в себе силы
    не пропускать занятия и соблюдать диету.

    131 | Подробнее 132 |
      133 |
    • 134 | 48 часов 135 | Без подзарядки 136 |
    • 137 |
    138 |
    139 |
  4. 140 | 141 |
  5. 142 |
    143 | квадрокоптер 144 |
    145 |
    146 | 03 147 |

    Порхает как бабочка, жалит как пчела!

    148 |

    Этот обычный, на первый взгляд, квадрокоптер оснащен
    мощным лазером, замаскированным под стандартную камеру.

    149 | Подробнее 150 |
      151 |
    • 152 | 800 м 153 | Дальность полета 154 |
    • 155 |
    • 156 | 50 м 157 | Радиус поражения 158 |
    • 159 |
    160 |
    161 |
  6. 162 |
163 |
164 |
165 | 166 | 190 |
191 | 192 |
193 | 194 |
195 | 196 |
197 |
198 |
199 |

Сервис интернет-магазина

200 | 201 |
    202 |
  • 203 | 204 |
  • 205 |
  • 206 | 207 |
  • 208 |
  • 209 | 210 |
  • 211 |
212 | 213 |
    214 |
  • 215 |

    Доставка

    216 |

    Мы с удовольствием доставим ваш товар прямо к вашему
    подъезду совершенно бесплатно! Ведь мы неплохо
    заработаем, поднимая его на ваш этаж.

    217 |
  • 218 | 219 |
  • 220 |

    Гарантия

    221 |

    Если из-за возгорания купленного у нас товара у вас сгорит дом —
    не переживайте, мы выдадим вам новый.
    Товар, не дом, конечно же.

    222 |
  • 223 | 224 |
  • 225 |

    Кредит

    226 |

    Залезть в долговую яму стало проще! Кредитные консультанты
    подберут для вас наиболее выгодные
    условия кредита. Выгодные для нашего банка, разумеется.

    227 |
  • 228 |
229 |
230 |
231 |
232 | 233 |
234 |
235 |

Гаджеты от популярных брендов

236 | 237 | 259 |
260 | 261 |
262 |
263 |

Информация о компании

264 |

О нас

265 |

Огромный выбор гаджетов не оставит равнодушным гика,
который есть в каждом из нас.

266 |

Мы можем доставить ваш товар в самые отдаленные точки
России! DEVICE работает со многими транспортными компаниями:

267 | 268 |
    269 |
  • Деловые линии
  • 270 |
  • Автотрейдинг
  • 271 |
  • ЖелДорЭкспедиция
  • 272 |
273 | 274 | Подробнее о нас 275 | mailto:example@example.com 276 |
277 | 278 |
279 |

Контакты

280 |

Вы можете забрать товар сами, заехав в наш офис. Заодно, вы сможете проверить работоспособность покупки. Всякое бывает.

281 | 282 | 283 | как добраться до офиса по адресу: Москва, улица Строителей, 15 284 | 285 | 286 | Напишите нам 287 |
288 |
289 |
290 |
291 | 292 | 360 | 361 | 391 | 392 | 398 | 399 |
400 |

asd

401 | 402 | 403 | 404 | 405 | 406 |
407 | 408 |
409 |

title

410 |

text

411 |
412 | 413 |
414 |

title

415 |
416 | 417 |
418 |

title

419 |

text

420 | 421 |
422 | 423 | 424 | 425 | 426 | Знак Cat Energy 427 | 428 | 429 | 430 | 431 | 432 | --------------------------------------------------------------------------------