├── .babelrc ├── .eslintrc ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── example ├── .babelrc ├── .gitignore ├── README.md ├── app.js ├── index.html ├── package.json └── webpack.config.js ├── package.json ├── src └── index.js └── test └── library.spec.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "globalReturn": true, 4 | "jsx": true, 5 | "modules": true 6 | }, 7 | 8 | "env": { 9 | "browser": true, 10 | "es6": true, 11 | "node": true 12 | }, 13 | 14 | "globals": { 15 | "document": false, 16 | "escape": false, 17 | "navigator": false, 18 | "unescape": false, 19 | "window": false, 20 | "describe": true, 21 | "before": true, 22 | "it": true, 23 | "expect": true, 24 | "sinon": true 25 | }, 26 | 27 | "parser": "babel-eslint", 28 | 29 | "plugins": [ 30 | 31 | ], 32 | 33 | "rules": { 34 | "block-scoped-var": 1, 35 | "brace-style": [1, "1tbs", { "allowSingleLine": true }], 36 | "camelcase": [1, { "properties": "always" }], 37 | "comma-dangle": [1, "never"], 38 | "comma-spacing": [1, { "before": false, "after": true }], 39 | "comma-style": [1, "last"], 40 | "complexity": 0, 41 | "consistent-return": 1, 42 | "consistent-this": 0, 43 | "curly": [1, "multi-line"], 44 | "default-case": 0, 45 | "dot-location": [1, "property"], 46 | "dot-notation": 0, 47 | "eol-last": 1, 48 | "eqeqeq": [1, "allow-null"], 49 | "func-names": 0, 50 | "func-style": 0, 51 | "generator-star-spacing": [1, "both"], 52 | "guard-for-in": 0, 53 | "handle-callback-err": [1, "^(err|error|anySpecificError)$" ], 54 | "indent": [1, 4, { "SwitchCase": 1 }], 55 | "key-spacing": [1, { "beforeColon": false, "afterColon": true }], 56 | "linebreak-style": 0, 57 | "max-depth": 0, 58 | "max-len": [1, 110, 4], 59 | "max-nested-callbacks": 0, 60 | "max-params": 0, 61 | "max-statements": 0, 62 | "new-cap": [1, { "newIsCap": true, "capIsNew": false }], 63 | "newline-after-var": [1, "always"], 64 | "new-parens": 1, 65 | "no-alert": 0, 66 | "no-array-constructor": 1, 67 | "no-bitwise": 0, 68 | "no-caller": 1, 69 | "no-catch-shadow": 0, 70 | "no-cond-assign": 1, 71 | "no-console": 0, 72 | "no-constant-condition": 0, 73 | "no-continue": 0, 74 | "no-control-regex": 1, 75 | "no-debugger": 1, 76 | "no-delete-var": 1, 77 | "no-div-regex": 0, 78 | "no-dupe-args": 1, 79 | "no-dupe-keys": 1, 80 | "no-duplicate-case": 1, 81 | "no-else-return": 1, 82 | "no-empty": 0, 83 | "no-empty-character-class": 1, 84 | "no-empty-label": 1, 85 | "no-eq-null": 0, 86 | "no-eval": 1, 87 | "no-ex-assign": 1, 88 | "no-extend-native": 1, 89 | "no-extra-bind": 1, 90 | "no-extra-boolean-cast": 1, 91 | "no-extra-parens": 0, 92 | "no-extra-semi": 0, 93 | "no-extra-strict": 0, 94 | "no-fallthrough": 1, 95 | "no-floating-decimal": 1, 96 | "no-func-assign": 1, 97 | "no-implied-eval": 1, 98 | "no-inline-comments": 0, 99 | "no-inner-declarations": [1, "functions"], 100 | "no-invalid-regexp": 1, 101 | "no-irregular-whitespace": 1, 102 | "no-iterator": 1, 103 | "no-label-var": 1, 104 | "no-labels": 1, 105 | "no-lone-blocks": 0, 106 | "no-lonely-if": 0, 107 | "no-loop-func": 0, 108 | "no-mixed-requires": 0, 109 | "no-mixed-spaces-and-tabs": [1, false], 110 | "no-multi-spaces": 0, 111 | "no-multi-str": 1, 112 | "no-multiple-empty-lines": [0, { "max": 1 }], 113 | "no-native-reassign": 1, 114 | "no-negated-in-lhs": 1, 115 | "no-nested-ternary": 0, 116 | "no-new": 1, 117 | "no-new-func": 1, 118 | "no-new-object": 1, 119 | "no-new-require": 1, 120 | "no-new-wrappers": 1, 121 | "no-obj-calls": 1, 122 | "no-octal": 1, 123 | "no-octal-escape": 1, 124 | "no-path-concat": 0, 125 | "no-plusplus": 0, 126 | "no-process-env": 0, 127 | "no-process-exit": 0, 128 | "no-proto": 1, 129 | "no-redeclare": 1, 130 | "no-regex-spaces": 1, 131 | "no-reserved-keys": 0, 132 | "no-restricted-modules": 0, 133 | "no-return-assign": 1, 134 | "no-script-url": 0, 135 | "no-self-compare": 1, 136 | "no-sequences": 1, 137 | "no-shadow": 0, 138 | "no-shadow-restricted-names": 1, 139 | "no-spaced-func": 1, 140 | "no-sparse-arrays": 1, 141 | "no-sync": 0, 142 | "no-ternary": 0, 143 | "no-throw-literal": 1, 144 | "no-trailing-spaces": 1, 145 | "no-undef": 1, 146 | "no-undef-init": 1, 147 | "no-undefined": 0, 148 | "no-underscore-dangle": 0, 149 | "no-unneeded-ternary": 1, 150 | "no-unreachable": 1, 151 | "no-unused-expressions": 0, 152 | "no-unused-vars": [1, { "vars": "all", "args": "none" }], 153 | "no-use-before-define": 1, 154 | "no-var": 0, 155 | "no-void": 0, 156 | "no-warning-comments": 0, 157 | "no-with": 1, 158 | "one-var": 0, 159 | "operator-assignment": 0, 160 | "operator-linebreak": [1, "after"], 161 | "padded-blocks": 0, 162 | "quote-props": 0, 163 | "quotes": [1, "single", "avoid-escape"], 164 | "radix": 1, 165 | "semi": [1, "always"], 166 | "semi-spacing": 0, 167 | "sort-vars": 0, 168 | "space-after-keywords": [1, "always"], 169 | "space-before-blocks": [1, "always"], 170 | "space-before-function-paren": [1, {"anonymous": "always", "named": "never"}], 171 | "space-in-brackets": 0, 172 | "space-in-parens": [1, "never"], 173 | "space-infix-ops": 1, 174 | "space-return-throw-case": 1, 175 | "space-unary-ops": [1, { "words": true, "nonwords": false }], 176 | "spaced-comment": [1, "always"], 177 | "strict": 0, 178 | "use-isnan": 1, 179 | "valid-jsdoc": 0, 180 | "valid-typeof": 1, 181 | "vars-on-top": 1, 182 | "wrap-iife": [1, "any"], 183 | "wrap-regex": 0, 184 | "yoda": [1, "never"] 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | lib 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Krasimir Tsonev 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 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | build_lib: 2 | node_modules/.bin/browserify src/index.js -o lib/react-turkce-textarea.browserify.js -t babelify -x react 3 | 4 | build_example: 5 | node_modules/.bin/browserify example/app.js -o example/bundle.browserify.js -t babelify 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Turkish Textarea 2 | 3 | İngilizce klavye ile yazılan yazıları otomatik olarak Türkçe karakterlerle düzelten, React için bir textarea bileşeni. 4 | 5 | Örneğin İngilizce karakterlerle Ustun Ozgur yazdığınızda bunu Üstün Özgür olarak düzeltir. 6 | 7 | ## Demo 8 | 9 | http://ustun.github.io/react-turkish-textarea/ 10 | 11 | ## Kurulum 12 | 13 | Önce gereksinimleri kurun. (Bu paketler peer dependency olduğu için npm 3'ten itibaren otomatik olarak kurulmayacaklar.) 14 | 15 | ```shell 16 | npm install react --save 17 | npm install turkish-deasciifier --save 18 | ``` 19 | Daha sonra `react-turkish-textarea` paketini kurun. 20 | 21 | ```shell 22 | npm install react-turkish-textarea --save 23 | ``` 24 | 25 | 26 | ## Kullanım 27 | 28 | 29 | ```js 30 | 31 | var TurkishTextArea = require('react-turkish-textarea'); 32 | 33 | var MyComponent = React.createClass({ 34 | 35 | render: function () { 36 | return ( 37 |
38 |

Ornek form

39 |
40 | 41 | 42 |
43 | ); 44 | 45 | } 46 | }); 47 | ``` 48 | 49 | Normal bir textarea bileşenine aktarabilen tüm özellikler TurkishTextarea bileşenine de aktarılabilir. 50 | 51 | ```js 52 | var MyComponent = React.createClass({ 53 | 54 | getInitialState: function () { 55 | return {value: ''}; 56 | }, 57 | 58 | render: function () { 59 | return ( 60 |
61 |

Ornek form

62 |
63 | 64 | 65 |
66 | ); 67 | 68 | } 69 | 70 | }); 71 | 72 | ``` 73 | 74 | ## Örnekler 75 | 76 | Örnek bir kullanım için example/ klasörüne göz atabilirsiniz. 77 | 78 | ## Nasıl Çalışır? 79 | 80 | Bu kod arkaplanda [Dr. Deniz Yüret](http://www.denizyuret.com/)'in Emacs icin yazdığı eklentiyi JavaScript'e 81 | çeviren [Mustafa Emre Acer](http://www.mustafaacer.com/)'in [Turkish Deasciifier](https://github.com/meacer/deasciifier/) kodunu React bileşeniyle 82 | entegre etmektedir. Deasciifier hakkında ayrıntılı bilgi için: 83 | 84 | - http://www.denizyuret.com/2006/11/emacs-turkish-mode.html 85 | - http://www.deasciifier.com/ 86 | 87 | ## npm'deki turkish-deasciifier paketi 88 | - Kodun orijinali: https://github.com/meacer/deasciifier/ 89 | - Mac OS X servisi hali: https://github.com/f/deasciifier 90 | - npm'deki kütüphanesi: https://github.com/ustun/turkish-deasciifier 91 | 92 | ## Scripts 93 | 94 | * `npm run build` - produces production version of your library under the `lib` folder 95 | * `npm run dev` - produces development version of your library and runs a watcher 96 | * `npm run test` - well ... it runs the tests :) 97 | -------------------------------------------------------------------------------- /example/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | bundle* 2 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Kullanım 2 | 3 | ``` 4 | npm install 5 | npm run build 6 | 7 | ``` 8 | 9 | Daha sonra index.html dosyasını açın. 10 | -------------------------------------------------------------------------------- /example/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import TurkishTextArea from 'react-turkish-textarea'; 5 | 6 | const MyComponent = React.createClass({ 7 | 8 | render: function () { 9 | return ( 10 |
11 |

Ornek form

12 |
13 | 14 | 15 |
16 | ); 17 | 18 | } 19 | }); 20 | 21 | ReactDOM.render(, document.getElementById('app-1')); 22 | 23 | 24 | const MyComponent2 = React.createClass({ 25 | 26 | getInitialState() { 27 | return {value: ''}; 28 | }, 29 | 30 | onChange(e) { 31 | this.setState({value: e.target.value.toUpperCase()}); 32 | }, 33 | 34 | render: function () { 35 | return ( 36 |
37 |

Ornek form

38 |
39 | 40 | 41 | 42 | Using external state: {this.state.value} 43 | 44 |
45 | ); 46 | 47 | } 48 | }); 49 | 50 | ReactDOM.render(, document.getElementById('app-2')); 51 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 24 | 25 | 26 |
27 |
28 |
29 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "babel-preset-es2015": "^6.3.13", 14 | "babel-preset-react": "^6.3.13", 15 | "webpack": "^1.12.10", 16 | "babel-loader": "^6.2.1" 17 | }, 18 | "dependencies": { 19 | "react": "^0.14.6", 20 | "react-dom": "^0.14.6", 21 | "react-turkish-textarea": "^0.2.0", 22 | "turkish-deasciifier": "1.0.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | var config = { 4 | entry: './app.js', 5 | devtool: 'source-map', 6 | output: { 7 | filename: 'bundle.js', 8 | }, 9 | module: { 10 | loaders: [ 11 | { 12 | test: /(\.jsx|\.js)$/, 13 | loader: 'babel', 14 | exclude: /(node_modules|bower_components)/ 15 | } 16 | ] 17 | } 18 | }; 19 | 20 | module.exports = config; 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-turkish-textarea", 3 | "version": "0.2.0", 4 | "description": "Ingilizce klavye ile yazilan yazilari otomatik olarak Turkce harflerle duzelten bir React textarea bileseni", 5 | "main": "lib/react-turkish-textarea.js", 6 | "scripts": { 7 | "build": "WEBPACK_ENV=build babel src/index.js -o lib/react-turkish-textarea.js", 8 | "dev": "WEBPACK_ENV=dev babel src/index.js -o lib/react-turkish-textarea.js --watch", 9 | "test": "tape ./test/*.spec.js" 10 | }, 11 | "devDependencies": { 12 | "babel": "6.3.13", 13 | "babel-cli": "^6.4.0", 14 | "babel-core": "^6.1.18", 15 | "babel-eslint": "4.1.3", 16 | "babel-preset-es2015": "^6.3.13", 17 | "babel-preset-react": "^6.3.13", 18 | "deasciifier": "0.0.2", 19 | "eslint": "1.7.2", 20 | "react": "^0.14.6", 21 | "webpack": "1.12.9" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/ustun/react-turkish-textarea.git" 26 | }, 27 | "keywords": [ 28 | "react-component", 29 | "textarea", 30 | "turkish", 31 | "react" 32 | ], 33 | "author": "Ustun Ozgur", 34 | "license": "MIT", 35 | "bugs": { 36 | "url": "https://github.com/ustun/react-turkish-textarea/issues" 37 | }, 38 | "homepage": "https://github.com/ustun/react-turkish-textarea", 39 | "peerDependencies": { 40 | "react": "^0.14.0", 41 | "turkish-deasciifier": "1.0.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Deasciifier from 'turkish-deasciifier'; 3 | 4 | const deascii = new Deasciifier(); 5 | 6 | const TurkishTextArea = React.createClass({ 7 | 8 | getDefaultProps() { 9 | return { 10 | enableCorrectionOnChange: true, 11 | enableCorrectionOnPaste: true, 12 | showToggleButtonForCorrectionOnChange: true, 13 | showToggleButtonForCorrectionOnPaste: true, 14 | showButtonForManualCorrection: true, 15 | labelForEnableCorrectionOnChange: 'Otomatik düzelt', 16 | labelForEnableCorrectionOnPaste: 'Yapıştırdıktan sonra otomatik düzelt', 17 | labelForManualCorrectionButton: 'Düzelt' 18 | }; 19 | }, 20 | 21 | getInitialState() { 22 | return { 23 | value: '', 24 | enableCorrectionOnPaste: this.props.enableCorrectionOnPaste, 25 | enableCorrectionOnChange: this.props.enableCorrectionOnChange 26 | }; 27 | }, 28 | 29 | setValue(value) { 30 | this.setState({value}); 31 | }, 32 | 33 | onChange(e) { 34 | if (!this.state.enableCorrectionOnChange) { 35 | if (this.props.onChange) { 36 | this.props.onChange(e); 37 | } else { 38 | this.setValue(e.target.value); 39 | } 40 | return; 41 | } 42 | 43 | // prevent calling onChange after onPaste, otherwise we get double input 44 | // FIXME: find a less hacky way 45 | if (this._justPasted) { 46 | this._justPasted = false; 47 | return; 48 | } 49 | 50 | const turkishValue = deascii.turkish_correct_last_word(e.target.value); 51 | 52 | if (this.props.onChange) { 53 | e.target.value = turkishValue; 54 | this.props.onChange(e); 55 | } else { 56 | this.setValue(turkishValue); 57 | } 58 | }, 59 | 60 | onPaste(e) { 61 | if (!this.state.enableCorrectionOnPaste) { 62 | this.props.onPaste && this.props.onPaste(e); 63 | return; 64 | } 65 | 66 | const pastedValue = e.clipboardData.getData('Text'); 67 | const turkishValue = deascii.deasciify(pastedValue); 68 | 69 | e.target.value = turkishValue; 70 | 71 | if (this.props.onChange) { 72 | this.props.onChange(e); 73 | } else { 74 | this.setValue(turkishValue); 75 | } 76 | this.props.onPaste && this.props.onPaste(e); 77 | 78 | this._justPasted = true; 79 | }, 80 | 81 | toggleEnableCorrectionOnChange() { 82 | this.setState({enableCorrectionOnChange: !this.state.enableCorrectionOnChange}); 83 | 84 | }, 85 | 86 | toggleEnableCorrectionOnPaste() { 87 | this.setState({enableCorrectionOnPaste: !this.state.enableCorrectionOnPaste}); 88 | 89 | }, 90 | 91 | correctManually() { 92 | const turkishValue = deascii.deasciify(this.refs.tx.value); 93 | 94 | if (this.props.onChange) { 95 | this.props.onChange({target: {value: turkishValue}}); 96 | } else { 97 | this.setValue(turkishValue); 98 | } 99 | 100 | this.refs.tx.focus(); 101 | 102 | }, 103 | 104 | render() { 105 | const customProps = { 106 | onChange: this.onChange, 107 | onPaste: this.onPaste, 108 | ref: 'tx' 109 | }; 110 | 111 | const finalProps = Object.assign({}, 112 | {value: this.state.value}, 113 | this.props, 114 | customProps); 115 | 116 | // var textArea = 117 | var showControls = this.props.showToggleButtonForCorrectionOnPaste || this.props.showToggleButtonForCorrectionOnChange; 118 | 119 | if (showControls) { 120 | return
121 |