PĂ«rshĂ«ndetje pĂ«rsĂ«ri. NjĂ« mĂ«ngjes i mrekullueshĂ«m pĂ«r ju . Sot do tĂ« ndaj me ju njĂ« nga dhimbjet e mia tĂ« kokĂ«s, konkretisht â çfarĂ« tĂ« bĂ«jmĂ« kur projekti shkruhet nga shumĂ« programues tĂ« niveleve tĂ« ndryshme, duke u bazuar nĂ« njĂ« aplikacion angular.

Isha mësuar që për një kohë të gjatë të punoja vetëm me ekipin tim, ku ne ishim pajtuar për rregullat e formatimit, komentimin, hapësirat etj. U përshtatëm me to dhe kemi jetuar të lumtur e të qetë. Në gëzimin tonë, madje publikova një artikull në Habr mbi . Prandaj, siç njihet ndryshe, ne përdorim vetëm tslint në pre-commit.
Dhe aty, ne u zgjeruam. U shfaq një projekt i ri me kod të trashëguar, dhe për ta, një grup i ri zhvilluesish me katër djem të mirë. Dhe çfarë ndodhi, nuk shkoi sipas planit.

Mendoj se shumë e dinë se puna me kod të trashëguar nuk është e këndshme. Në kujtesën time kam pasur vetëm një projekt që më ka emocionuar, ndërsa të tjerat⊠Po për çfarë po flas?) Ah po.
Me tĂ« vĂ«rtetĂ«, arkitektura nĂ« projekt kishte shumĂ« pĂ«r tĂ« dĂ«shmuar, dhe komentet dhe tipizimi ishin njĂ« Ă«ndĂ«rr pĂ«r ne. NĂ« njĂ« moment, fillova tĂ« mĂ«rzitem nga fakti se dokumentacioni ynĂ« mbi rregullat e formatimit nuk funksiononte, komentet nuk shkruhen, tip â çfarĂ« Ă«shtĂ« kjo?). KĂ«shtu qĂ« duhej bĂ«rĂ« diçka.
Për ata që mezi presin të dinë të gjitha hapat menjëherë:
Ne ndamë tslint në rregulla të buta (për pre-commit) dhe rregulla të forta (për ide, për t'i kujtuar zhvilluesit se kishin harruar të bënin diçka)
Vendosëm auto-fiksimin e mundshëm të rregullave nga tslint i fortë në pre-commit
Shkruam rregulla për prettier
Dançim me bubullimë për të ekzekutuar ng lint me lint-staged
Hapi i parĂ« â ndaje dhe sundo
Kur më erdhi ideja për të ashpërsuar rregullat e linterit, mendoja se do të na kaplohej. Kodi është trashëguar. Duhet të kuptohet, dhe në një volum të tillë mund të mbesim të mbytur. U mor vendimi për të krijuar një linter të dytë për ide, i cili do të na shqetësonte dhe do të na bënte të shkruajmë jsdoc për metodat dhe prop, të shkruajmë interfaca ose të famshmin onPush dhe të tjera.
Kështu që në rrënjë ne filluam me 2 skedarë tslin:
tsconfig.json
{
"rulesDirectory": [
"node_modules/codelyzer"
],
"rules": {
"arrow-return-shorthand": true,
"callable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"deprecation": {
"severity": "warn"
},
"eofline": true,
"forin": true,
"import-blacklist": [
true,
"rxjs/Rx"
],
"import-spacing": true,
"indent": [
true,
"spaces"
],
"interface-over-type-literal": true,
"label-position": true,
"max-line-length": [
true,
200
],
"member-access": false,
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-super": true,
"no-empty": false,
"no-empty-interface": true,
"no-eval": true,
"no-inferrable-types": [
false,
"ignore-params"
],
"no-duplicate-imports": true,
"no-misused-new": true,
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-shadowed-variable": false,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": [
true,
"ignore-comments",
"ignore-jsdoc"
],
"no-unnecessary-initializer": true,
"no-unused-expression": true,
"no-use-before-declare": false,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true,
"quotemark": [
true,
"single"
],
"radix": false,
"semicolon": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"unified-signatures": true,
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
],
"no-output-on-prefix": false,
"no-inputs-metadata-property": true,
"no-outputs-metadata-property": true,
"no-host-metadata-property": true,
"no-input-rename": false,
"no-output-rename": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true,
"no-consecutive-blank-lines": true
}
}tslint.ide_only.json
{
"rulesDirectory": [
"node_modules/codelyzer"
],
"rules": {
"completed-docs": [
true,
{
"properties": true,
"methods": true
}
],
"no-angle-bracket-type-assertion": true,
"no-any": true,
"prefer-output-readonly": true,
"prefer-on-push-component-change-detection": true,
"array-type": [
true,
"array"
],
"typedef": [
true,
"call-signature",
"arrow-call-signature"
],
"arrow-return-shorthand": true,
"callable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"deprecation": {
"severity": "warn"
},
"eofline": true,
"forin": true,
"import-blacklist": [
true,
"rxjs/Rx"
],
"import-spacing": true,
"indent": [
true,
"spaces"
],
"interface-over-type-literal": true,
"label-position": true,
"max-line-length": [
true,
200
],
"member-access": [
true,
"check-parameter-property",
"check-accessor"
],
"member-ordering": [
true,
{
"order": [
"public-static-field",
"protected-static-field",
"private-static-field",
"public-instance-field",
"protected-instance-field",
"private-instance-field",
"constructor",
"public-static-method",
"protected-static-method",
"private-static-method",
"public-instance-method",
"protected-instance-method",
"private-instance-method"
]
}
],
"no-arg": true,
"no-bitwise": true,
"no-console": true,
"no-construct": true,
"no-debugger": true,
"no-duplicate-super": true,
"no-empty": false,
"no-empty-interface": true,
"no-duplicate-switch-case": true,
"no-eval": true,
"no-inferrable-types": [
false,
"ignore-params"
],
"no-duplicate-imports": true,
"one-variable-per-declaration": true,
"no-misused-new": true,
"no-non-null-assertion": true,
"prefer-template": [
true,
"allow-single-concat"
],
"ordered-imports": true,
"no-redundant-jsdoc": true,
"no-shadowed-variable": false,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": [
true,
"ignore-comments",
"ignore-jsdoc"
],
"ban": [
true,
{
"name": [
"Object",
"assign"
],
"message": "Përdorni cloneDeep (lodash) për kopjimin e objektit"
}
],
"max-classes-per-file": [
true,
1
],
"cyclomatic-complexity": [
true,
6
],
"static-this": true,
"no-unnecessary-initializer": true,
"no-unused-expression": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true,
"quotemark": [
true,
"single"
],
"radix": false,
"semicolon": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"unified-signatures": true,
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
],
"no-output-on-prefix": false,
"no-inputs-metadata-property": true,
"no-outputs-metadata-property": true,
"no-host-metadata-property": true,
"no-input-rename": false,
"no-output-rename": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true,
"no-consecutive-blank-lines": true
}
}Në skedar src/tslint Ne zëvendësuam tslint standard me ide
src/tslint.json
{
"extends": "../tslint.ide_only.json",
"rules": {
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
]
}
}Đ ĐżĐŸĐżŃаĐČОл запŃŃĐș ĐœĐ°ŃĐ”ĐłĐŸ Đ»ĐžĐœŃĐ”Ńа ĐČ ŃĐșŃĐžŃĐ°Ń package.json
ng lint --tslint-config ./tslint.json --fix`Pas kësaj, filluam të ndiheshim ngushtë me gjërat e theksuara që nevojonin korrigjim.
Hapi i dytĂ« â korrigjo disa pika

Tslint ka rregulla me ka ndreqës. Pra, le të përfitojmë.
tslint --project tslint.ide_only.json --fix --forceKëtu ne ekzekutojmë rregullat e lintrit të fortë me auto-rregullimin e parametrave të disponueshëm dhe i themi asaj komande që të mos kthejë gabime (qëllimi ynë përfundimisht është të bëjmë auto-korrigjimin).
Hapi i tretĂ« â shkruaj me bukuri
Kur secili shkruan në stilin e tij, përfundimisht bëhet lodhëse. Kodi duhet të shkruhet në një mënyrë që të duket se e bën një njeri. Për këtë, unë krijova prettier me konfigurimet e mëposhtme:
.prettierr.yaml
printWidth: 200 # Numri maksimal i simboleve në linjë
tabWidth: 2 # Hapsira në tab
singleQuote: true # Përdorimi i thonjëzave të vetme
trailingComma: all # Përdorimi i presjeve ku është e mundur
arrowParens: always # Funksionet me arrow duken (x) => x
overrides:
- files: "*.ts" # Kontrolli i skedarëve *.ts
options:
parser: typescript # Gjuha në skedarët *.tsDhe shtova komandën: prettier --write --config .prettierr.yaml
Hapi i katĂ«rt â Si do tĂ« urdhĂ«rosh tĂ« gjithĂ« kĂ«tĂ« tĂ« ekzekutohet?
Tani le të shqyrtojmë më në detaje se si ta ekzekutojmë të gjithë këtë. Për të punuar kështu, na nevojitet të shkarkojmë bibliotekat e mëposhtme:
npm i -D prettier lint-staged huskyMe husky do tĂ« lidhim ekzekutimin e komandave tona nĂ« hook-un git â pre-commit. lint-staged do tĂ« ekzekutojĂ« komandat tona nĂ« varĂ«si tĂ« skedarĂ«ve tĂ« ndryshuar ( gjithashtu do tĂ« vendosĂ« kĂ«ta skedarĂ« nĂ« komandat tona).
Doja të përshkruaja gjithashtu një problem me të cilin kam hasur. Në projektin tonë ne përdorim ng lint. Kur e përdorim në lidhje me lint-staged, skedarët e ndryshuar shtohen në komandën tonë. Ng lint ka çelësin për këtë --files, por, siç kam kuptuar, ai nuk e sheh paketën e skedarëve, dhe i nevojitet të shtohet ky çelës për secilin skedare. Për këtë, më duhej të krijoja një skedar:
lint.sh
#!/bin/bash
PROJECT=$1
shift
SOURCES=$@
DESTINATIONS=""
DELIMITER=""
for src in $SOURCES
do
DELIMITER=" --files "
DESTINATIONS="$DESTINATIONS$DELIMITER${src}"
done
ng lint $PROJECT --tslint-config ./tslint.json $DESTINATIONSPër të ekzekutuar këtë skedar, duhet të kalojmë emrin e projektit. Ai është në skedarin angular.json në pronën project. Në rastin tim, është partner-account dhe partner-account-e2e. Më nevojitet i pari.
Të kthehem te konfigurimi. Tani package.json ynë duket kështu:
"husky": {
"hooks": {
"pre-commit": "lint-staged --relative"
}
},
"lint-staged": {
"*.{ts,js}": [
"prettier --write --config .prettierr.yaml",
"tslint --project tslint.ide_only.json --fix --force",
"sh lint.sh partner-account",
"git add"
],
"*.{html,scss,css}": [
"prettier --write --config .prettierr.yaml",
"git add"
]
},Kujdesi për lint-staged --relative. Parametri --relative është e detyrueshme. Tani, kur bëjmë commit, fillon lint-staged. Ai përzgjedh skedarët dhe ekzekuton një listë komandash në varësi të tyre.
FatkeqĂ«sisht, kjo nuk anullon rishikimin e kodit, por ai Ă«shtĂ« bĂ«rĂ« shumĂ« mĂ« i pastĂ«r. Dua tĂ« theksoj se kam filluar tĂ« i kujtoj mĂ« rrallĂ« zhvilluesve pĂ«r modifikatorĂ«t e aksesit, pĂ«rshkrimin e metodave dhe pronave, dhe krijimtaria e tyre Ă«shtĂ« shkruar nĂ« njĂ« stil tĂ« unifikuar (pothuajse đ ).
P.S. â Faleminderit pĂ«r imazhet PM-sĂ« sonĂ«.
Burimi: habr.com
