├── .editorconfig
├── .gitignore
├── .jscsrc
├── .jshintrc
├── .npmignore
├── Jenkinsfile
├── README.md
├── docs
├── CNAME
├── _config.yml
├── _includes
│ ├── footer.html
│ ├── head.html
│ ├── header.html
│ ├── icon-github.html
│ ├── icon-github.svg
│ ├── icon-twitter.html
│ └── icon-twitter.svg
├── _layouts
│ ├── default.html
│ ├── page.html
│ └── post.html
├── _sass
│ ├── _base.scss
│ ├── _layout.scss
│ └── _syntax-highlighting.scss
├── css
│ ├── colors.css
│ ├── components.css
│ ├── defaults.css
│ ├── elements.css
│ ├── images.css
│ ├── img
│ │ └── socials.png
│ ├── layout.css
│ ├── main.scss
│ └── spacings.css
├── documentation.md
├── feed.xml
├── img
│ ├── logo.png
│ └── socials.png
├── index.html
└── js
│ └── textversion.js
├── gulpfile.js
├── package-lock.json
├── package.json
├── spec
└── textversionsSpec.js
└── src
└── textversion.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = tab
5 | indent_size = 4
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 |
10 | [package.json]
11 | indent_size = 2
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | junitresults.xml
4 | docs/_site
5 | docs/.sass-cache
--------------------------------------------------------------------------------
/.jscsrc:
--------------------------------------------------------------------------------
1 | {
2 | "disallowDanglingUnderscores":true,
3 | "disallowEmptyBlocks":true,
4 | "disallowMixedSpacesAndTabs":true,
5 | "disallowMultiLineTernary":true,
6 | "disallowMultipleLineStrings":true,
7 | "disallowMultipleSpaces":true,
8 | "disallowNestedTernaries":true,
9 | "disallowNewlineBeforeBlockStatements":true,
10 | "disallowSpacesInCallExpression":true,
11 | "disallowSpacesInAnonymousFunctionExpression":{
12 | "beforeOpeningRoundBrace":true
13 | },
14 | "disallowSpaceBeforeSemicolon":true,
15 | "disallowSpaceBeforeComma":true,
16 | "disallowSpaceAfterPrefixUnaryOperators":[
17 | "+",
18 | "-",
19 | "~",
20 | "!"
21 | ],
22 | "disallowSpaceAfterObjectKeys":true,
23 | "disallowSpacesInsideParenthesizedExpression":true,
24 | "disallowSpacesInsideParentheses":true,
25 | "disallowSpacesInsideObjectBrackets":true,
26 | "disallowSpacesInsideBrackets":true,
27 | "disallowSpacesInsideArrayBrackets":"all",
28 | "disallowSpacesInNamedFunctionExpression":{
29 | "beforeOpeningRoundBrace":true
30 | },
31 | "disallowSpacesInFunction":{
32 | "beforeOpeningRoundBrace":true
33 | },
34 | "disallowSpacesInFunctionExpression":{
35 | "beforeOpeningRoundBrace":true
36 | },
37 | "disallowSpacesInFunctionDeclaration":{
38 | "beforeOpeningRoundBrace":true
39 | },
40 | "requireEarlyReturn":true,
41 | "requireCurlyBraces":true,
42 | "requireCommaBeforeLineBreak":true,
43 | "requireCapitalizedConstructors":true,
44 | "requireBlocksOnNewline":true,
45 | "requireCamelCaseOrUpperCaseIdentifiers":true,
46 | "requireAlignedMultilineParams":true,
47 | "disallowUnusedParams":true,
48 | "disallowTrailingWhitespace":true,
49 | "disallowTrailingComma":true,
50 | "requireLineBreakAfterVariableAssignment":true,
51 | "requireSpacesInNamedFunctionExpression":{
52 | "beforeOpeningCurlyBrace":true
53 | },
54 | "requireSpacesInGenerator":{
55 | "afterStar":true
56 | },
57 | "requireSpacesInFunction":{
58 | "beforeOpeningCurlyBrace":true
59 | },
60 | "requireSpacesInFunctionExpression":{
61 | "beforeOpeningCurlyBrace":true
62 | },
63 | "requireSpacesInFunctionDeclaration":{
64 | "beforeOpeningCurlyBrace":true
65 | },
66 | "requireSpacesInForStatement":true,
67 | "requireSpacesInConditionalExpression":{
68 | "afterTest":true,
69 | "beforeConsequent":true,
70 | "afterConsequent":true,
71 | "beforeAlternate":true
72 | },
73 | "requireSpacesInAnonymousFunctionExpression":{
74 | "beforeOpeningCurlyBrace":true
75 | },
76 | "requireSpaceBetweenArguments":true,
77 | "requireSpaceBeforeObjectValues":true,
78 | "requireSpaceBeforeKeywords":[
79 | "else",
80 | "while",
81 | "catch"
82 | ],
83 | "requireSpaceBeforeBlockStatements":1,
84 | "requireSpaceBeforeBinaryOperators":true,
85 | "requireSpaceAfterKeywords":[
86 | "do",
87 | "for",
88 | "if",
89 | "else",
90 | "switch",
91 | "case",
92 | "try",
93 | "catch",
94 | "void",
95 | "while",
96 | "with",
97 | "return",
98 | "typeof"
99 | ],
100 | "requireSpaceAfterComma":true,
101 | "requireSpaceAfterBinaryOperators":true,
102 | "requireSemicolons":true,
103 | "requireParenthesesAroundIIFE":true,
104 | "requirePaddingNewLinesInObjects":true,
105 | "requirePaddingNewLinesBeforeExport":true,
106 | "requirePaddingNewLinesAfterUseStrict":true,
107 | "requirePaddingNewLineAfterVariableDeclaration":true,
108 | "requireObjectKeysOnNewLine":true,
109 | "requireLineFeedAtFileEnd":true,
110 | "validateIndentation":"\t",
111 | "validateLineBreaks":"LF",
112 | "validateParameterSeparator":", ",
113 | "validateQuoteMarks":"\""
114 | }
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "asi":false,
3 | "boss":false,
4 | "debug":false,
5 | "evil":false,
6 | "bitwise":true,
7 | "browser":true,
8 | "browserify":true,
9 | "curly":true,
10 | "eqeqeq":true,
11 | "funcscope":true,
12 | "jasmine":true,
13 | "mocha":true,
14 | "maxcomplexity":32,
15 | "maxdepth":12,
16 | "maxparams":12,
17 | "nocomma":true,
18 | "nonbsp":true,
19 | "nonew":true,
20 | "notypeof":false,
21 | "node":true,
22 | "esnext":true,
23 | "globals":{
24 | "jquery": true,
25 | "$": true
26 | },
27 | "globalstrict":false,
28 | "immed":true,
29 | "newcap":true,
30 | "plusplus":true,
31 | "predef":[
32 | "$"
33 | ],
34 | "phantom":true,
35 | "shadow":true,
36 | "singleGroups":false,
37 | "quotmark":"double",
38 | "strict":false,
39 | "undef":true,
40 | "unused":true,
41 | "validthis":true,
42 | "withstmt":false
43 | }
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | ### Node ###
2 | # Logs
3 | logs
4 | *.log
5 | npm-debug.log*
6 |
7 | # Runtime data
8 | pids
9 | *.pid
10 | *.seed
11 |
12 | # Directory for instrumented libs generated by jscoverage/JSCover
13 | lib-cov
14 |
15 | # Coverage directory used by tools like istanbul
16 | coverage
17 |
18 | # node-waf configuration
19 | .lock-wscript
20 |
21 | # Compiled binary addons (http://nodejs.org/api/addons.html)
22 | build/Release
23 |
24 | # Dependency directories
25 | node_modules
26 | jspm_packages
27 |
28 | # Optional npm cache directory
29 | .npm
30 |
31 | # Optional REPL history
32 | .node_repl_history
33 |
34 | ### SublimeText ###
35 | # cache files for sublime text
36 | *.tmlanguage.cache
37 | *.tmPreferences.cache
38 | *.stTheme.cache
39 |
40 | # workspace files are user-specific
41 | *.sublime-workspace
42 |
43 | # project files should be checked into the repository, unless a significant
44 | # proportion of contributors will probably not be using SublimeText
45 | *.sublime-project
46 |
47 | **/*.build.js
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | pipeline {
2 | agent any
3 | tools {
4 | nodejs 'Node Argon [4.6.0] + mocha, gulp, grunt, jasmine'
5 | }
6 | stages {
7 | stage('build') {
8 | steps {
9 | sh 'npm install'
10 | }
11 | }
12 | stage('test') {
13 | steps {
14 | sh 'npm test'
15 | }
16 | }
17 | stage('publish test results') {
18 | steps {
19 | junit 'junitresults.xml'
20 | step(
21 | [$class: 'CoberturaPublisher',
22 | autoUpdateHealth: false,
23 | autoUpdateStability: false,
24 | coberturaReportFile: 'coverage/cobertura-coverage.xml',
25 | failUnhealthy: false,
26 | failUnstable: false,
27 | maxNumberOfBuilds: 0,
28 | onlyStable: false,
29 | sourceEncoding: 'ASCII',
30 | zoomCoverageChart: false]
31 | )
32 | }
33 | }
34 | stage('publish') {
35 | when {
36 | branch "master"
37 | }
38 | steps {
39 | withNPM(npmrcConfig:'npmrc-global') {
40 | sh 'npm publish'
41 | }
42 | }
43 | }
44 | }
45 | post {
46 | always {
47 | cleanWs()
48 | }
49 | failure {
50 | slackSend color: 'danger', message: "FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})"
51 | }
52 | success {
53 | slackSend color: 'good', message: "SUCCESS: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})"
54 | }
55 | unstable {
56 | slackSend color: 'warning', message: "UNSTABLE: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})"
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # textversionjs
2 |
3 | Generate the text version of your HTML email in a second.
4 |
5 | This tool is an open source project. Feel free to use it any time in your projects!
6 |
7 | ## htmlToPlainText
8 |
9 | The function that generates plain text from email htmls.
10 |
11 | ### Params
12 |
13 | Param | Type | Required | Default value | Description
14 | --- |--- |--- |--- |---
15 | htmlText | string | Yes | | The html version of the email
16 | styleConfig | json/javascript object | No | | Options for converting
17 |
18 | ### styleConfig
19 |
20 | Param | Type | Required | Default value | Description
21 | --- |--- |--- |--- |---
22 | linkProcess | function | No | | Callback function to customize links appearance
23 | imgProcess | function | No | | Callback function to customize image appearance
24 | headingStyle | string | No | "underline" | Define heading appearance, options: "underline", "linebreak", "hashify"
25 | listStyle | string | No | "indention" | Define list appearance, options: "indention", "linebreak"
26 | uIndentionChar | string | No | "-" | If listStyle is indention, uIndentionChar is the character that fills the indention for unordered lists
27 | oIndentionChar | string | No | "-" | If listStyle is indention, oIndentionChar is the character that fills the indention for ordered lists after the heading number
28 | listIndentionTabs | int | No | 3 | If listStyle is indention, listIndentionTabs is the width of the indention
29 | keepNbsps | boolean | No | false | Define the behaviour of the non-braking spaces. If set to true, nbsps are not collapsed to single space.
30 |
31 | ### linkProcess
32 |
33 | Param | Type | Required | Default value | Description
34 | --- |--- |--- |--- |---
35 | href | string | Yes | | The destination (href property) of the link
36 | linkText | string | Yes | | The text of the link
37 |
38 | ### imgProcess
39 |
40 | Param | Type | Required | Default value | Description
41 | --- |--- |--- |--- |---
42 | src | string | Yes | | The source (src property) of the image
43 | alt | string | Yes | | The alternative text (alt property) of the image
44 |
45 | ### Examples
46 |
47 | #### Simple conversion with default style
48 |
49 | ```js
50 | var textVersion = require("textversionjs");
51 | var htmlText = "" +
52 | "
" +
53 | "Lorem ipsum dolor sic amet " +
54 | "Lorem ipsum sic amet " +
55 | "Lorem ipsum dolor sic amet
" +
56 | "" +
59 | "" +
60 | "";
61 |
62 | var plainText = textVersion(htmlText);
63 | // returns
64 | // "Lorem ipsum [dolor] (http://foo.foo) sic amet
65 | // Lorem ipsum ![foo] (http://foo.jpg) sic amet
66 | // Lorem ipsum dolor
67 | // sic amet"
68 |
69 | ```
70 |
71 | #### Customize link appearance
72 |
73 | ```js
74 | var textVersion = require("textversionjs");
75 | var htmlText = "Lorem ipsum dolor sic amet
";
76 |
77 | var styleConfig = {
78 | linkProcess: function(href, linkText){
79 | return linkText + " " + "(" + href + ")";
80 | }
81 | };
82 |
83 | var plainText = textVersion(htmlText, styleConfig);
84 | // returns "Lorem ipsum (http://foo.foo) dolor sic amet"
85 |
86 | ```
87 |
88 | #### Customize headings
89 |
90 | ```js
91 | var textVersion = require("textversionjs");
92 |
93 | var htmlText = "Lorem ipsum " +
94 | "Lorem ipsum dolor sic amet
";
95 |
96 | var styleConfig = {
97 | headingStyle: "hashify"
98 | };
99 |
100 | var plainText = textVersion(htmlText, styleConfig);
101 | // returns
102 | // "# Lorem ipsum
103 | //
104 | // Lorem ipsum dolor sic amet"
105 |
106 | ```
107 |
108 | #### Customize lists
109 |
110 | ```js
111 | var textVersion = require("textversionjs");
112 | var htmlText = "" +
113 | "Lorem " +
114 | "ipsum " +
115 | " " +
116 | "" +
117 | "Lorem " +
118 | "ipsum " +
119 | " ";
120 |
121 | var styleConfig = {
122 | headingStyle: "indention",
123 | uIndentionChar: ".";
124 | listIndentionTabs: 2;
125 | };
126 |
127 | var plainText = textVersion(htmlText, styleConfig);
128 | // returns "
129 | // ..Lorem
130 | // ..ipsum
131 | // 3.Lorem
132 | // 4.ipsum"
133 | ```
134 |
135 | Try it online in our [Demo page](http://emailtextversion.com/)!
136 |
137 | Don't forget to check out our other open source projects at [EDMdesigner](https://edmdesigner.com/).
138 |
139 | Follow us on [github](https://github.com/EDMdesigner) and [twitter](https://twitter.com/EDMdesigner)!
140 |
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | textversionjs.com
2 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | # Welcome to Jekyll!
2 | #
3 | # This config file is meant for settings that affect your whole blog, values
4 | # which you are expected to set up once and rarely need to edit after that.
5 | # For technical reasons, this file is *NOT* reloaded automatically when you use
6 | # 'jekyll serve'. If you change this file, please restart the server process.
7 |
8 | # Site settings
9 | title: TextVersionJS
10 | email: info@edmdesigner.com
11 | description: > # this means to ignore newlines until "baseurl:"
12 | Generate the text version of your HTML email in a second.
13 | baseurl: "" # the subpath of your site, e.g. /blog
14 | url: "http://textversionjs.com" # the base hostname & protocol for your site
15 | gaCode: UA-42954042-8
16 | facebook_username: edmdesigner
17 | twitter_username: EDMdesigner
18 | github_username: EDMdesigner
19 | linkedin_username: company/edmdesigner-com
20 | google_username: +Edmdesigner
21 | projectname: textversionjs
22 |
23 | # Build settings
24 | markdown: kramdown
25 |
--------------------------------------------------------------------------------
/docs/_includes/footer.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/_includes/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {% if page.title %}{{ page.title | escape }}{% else %}{{ site.title | escape }}{% endif %}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/docs/_includes/header.html:
--------------------------------------------------------------------------------
1 |
2 |
55 |
56 |
--------------------------------------------------------------------------------
/docs/_includes/icon-github.html:
--------------------------------------------------------------------------------
1 | {% include icon-github.svg %} {{ include.username }}
2 |
--------------------------------------------------------------------------------
/docs/_includes/icon-github.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_includes/icon-twitter.html:
--------------------------------------------------------------------------------
1 | {{ include.username }}
2 |
--------------------------------------------------------------------------------
/docs/_includes/icon-twitter.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {% include head.html %}
5 |
6 |
7 |
8 | {% include header.html %}
9 |
10 |
11 |
12 | {{ content }}
13 |
14 |
15 |
16 | {% include footer.html %}
17 |
18 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/docs/_layouts/page.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | ---
4 |
5 |
6 |
9 |
10 |
11 | {{ content }}
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/docs/_layouts/post.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | ---
4 |
5 |
6 |
10 |
11 |
12 | {{ content }}
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/docs/_sass/_base.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Reset some basic elements
3 | */
4 | body, h1, h2, h3, h4, h5, h6,
5 | p, blockquote, pre, hr,
6 | dl, dd, ol, ul, figure {
7 | margin: 0;
8 | padding: 0;
9 | }
10 |
11 |
12 |
13 | /**
14 | * Basic styling
15 | */
16 | body {
17 | font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family;
18 | color: $text-color;
19 | background-color: $background-color;
20 | -webkit-text-size-adjust: 100%;
21 | -webkit-font-feature-settings: "kern" 1;
22 | -moz-font-feature-settings: "kern" 1;
23 | -o-font-feature-settings: "kern" 1;
24 | font-feature-settings: "kern" 1;
25 | font-kerning: normal;
26 | }
27 |
28 |
29 |
30 | /**
31 | * Set `margin-bottom` to maintain vertical rhythm
32 | */
33 | h1, h2, h3, h4, h5, h6,
34 | p, blockquote, pre,
35 | ul, ol, dl, figure,
36 | %vertical-rhythm {
37 | margin-bottom: $spacing-unit / 2;
38 | }
39 |
40 |
41 |
42 | /**
43 | * Images
44 | */
45 | img {
46 | max-width: 100%;
47 | vertical-align: middle;
48 | }
49 |
50 |
51 |
52 | /**
53 | * Figures
54 | */
55 | figure > img {
56 | display: block;
57 | }
58 |
59 | figcaption {
60 | font-size: $small-font-size;
61 | }
62 |
63 |
64 |
65 | /**
66 | * Lists
67 | */
68 | ul, ol {
69 | margin-left: $spacing-unit;
70 | }
71 |
72 | li {
73 | > ul,
74 | > ol {
75 | margin-bottom: 0;
76 | }
77 | }
78 |
79 |
80 |
81 | /**
82 | * Headings
83 | */
84 | h1, h2, h3, h4, h5, h6 {
85 | font-weight: $base-font-weight;
86 | }
87 |
88 |
89 |
90 | /**
91 | * Links
92 | */
93 | a {
94 | color: $brand-color;
95 | text-decoration: none;
96 |
97 | &:visited {
98 | color: darken($brand-color, 15%);
99 | }
100 |
101 | &:hover {
102 | color: $text-color;
103 | text-decoration: underline;
104 | }
105 | }
106 |
107 |
108 |
109 | /**
110 | * Blockquotes
111 | */
112 | blockquote {
113 | color: $grey-color;
114 | border-left: 4px solid $grey-color-light;
115 | padding-left: $spacing-unit / 2;
116 | font-size: 18px;
117 | letter-spacing: -1px;
118 | font-style: italic;
119 |
120 | > :last-child {
121 | margin-bottom: 0;
122 | }
123 | }
124 |
125 |
126 |
127 | /**
128 | * Code formatting
129 | */
130 | pre,
131 | code {
132 | font-size: 15px;
133 | border: 1px solid $grey-color-light;
134 | border-radius: 3px;
135 | background-color: #eef;
136 | }
137 |
138 | code {
139 | padding: 1px 5px;
140 | }
141 |
142 | pre {
143 | padding: 8px 12px;
144 | overflow-x: auto;
145 |
146 | > code {
147 | border: 0;
148 | padding-right: 0;
149 | padding-left: 0;
150 | }
151 | }
152 |
153 |
154 |
155 | /**
156 | * Wrapper
157 | */
158 | .wrapper {
159 | max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2));
160 | max-width: calc(#{$content-width} - (#{$spacing-unit} * 2));
161 | margin-right: auto;
162 | margin-left: auto;
163 | padding-right: $spacing-unit;
164 | padding-left: $spacing-unit;
165 | @extend %clearfix;
166 |
167 | @include media-query($on-laptop) {
168 | max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit}));
169 | max-width: calc(#{$content-width} - (#{$spacing-unit}));
170 | padding-right: $spacing-unit / 2;
171 | padding-left: $spacing-unit / 2;
172 | }
173 | }
174 |
175 |
176 |
177 | /**
178 | * Clearfix
179 | */
180 | %clearfix {
181 |
182 | &:after {
183 | content: "";
184 | display: table;
185 | clear: both;
186 | }
187 | }
188 |
189 |
190 |
191 | /**
192 | * Icons
193 | */
194 | .icon {
195 |
196 | > svg {
197 | display: inline-block;
198 | width: 16px;
199 | height: 16px;
200 | vertical-align: middle;
201 |
202 | path {
203 | fill: $grey-color;
204 | }
205 | }
206 | }
207 |
--------------------------------------------------------------------------------
/docs/_sass/_layout.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Site header
3 | */
4 | .site-header {
5 | border-top: 5px solid $grey-color-dark;
6 | border-bottom: 1px solid $grey-color-light;
7 | min-height: 56px;
8 |
9 | // Positioning context for the mobile navigation icon
10 | position: relative;
11 | }
12 |
13 | .site-title {
14 | font-size: 26px;
15 | font-weight: 300;
16 | line-height: 56px;
17 | letter-spacing: -1px;
18 | margin-bottom: 0;
19 | float: left;
20 |
21 | &,
22 | &:visited {
23 | color: $grey-color-dark;
24 | }
25 | }
26 |
27 | .site-nav {
28 | float: right;
29 | line-height: 56px;
30 |
31 | .menu-icon {
32 | display: none;
33 | }
34 |
35 | .page-link {
36 | color: $text-color;
37 | line-height: $base-line-height;
38 |
39 | // Gaps between nav items, but not on the last one
40 | &:not(:last-child) {
41 | margin-right: 20px;
42 | }
43 | }
44 |
45 | @include media-query($on-palm) {
46 | position: absolute;
47 | top: 9px;
48 | right: $spacing-unit / 2;
49 | background-color: $background-color;
50 | border: 1px solid $grey-color-light;
51 | border-radius: 5px;
52 | text-align: right;
53 |
54 | .menu-icon {
55 | display: block;
56 | float: right;
57 | width: 36px;
58 | height: 26px;
59 | line-height: 0;
60 | padding-top: 10px;
61 | text-align: center;
62 |
63 | > svg {
64 | width: 18px;
65 | height: 15px;
66 |
67 | path {
68 | fill: $grey-color-dark;
69 | }
70 | }
71 | }
72 |
73 | .trigger {
74 | clear: both;
75 | display: none;
76 | }
77 |
78 | &:hover .trigger {
79 | display: block;
80 | padding-bottom: 5px;
81 | }
82 |
83 | .page-link {
84 | display: block;
85 | padding: 5px 10px;
86 |
87 | &:not(:last-child) {
88 | margin-right: 0;
89 | }
90 | margin-left: 20px;
91 | }
92 | }
93 | }
94 |
95 |
96 |
97 | /**
98 | * Site footer
99 | */
100 | .site-footer {
101 | border-top: 1px solid $grey-color-light;
102 | padding: $spacing-unit 0;
103 | }
104 |
105 | .footer-heading {
106 | font-size: 18px;
107 | margin-bottom: $spacing-unit / 2;
108 | }
109 |
110 | .contact-list,
111 | .social-media-list {
112 | list-style: none;
113 | margin-left: 0;
114 | }
115 |
116 | .footer-col-wrapper {
117 | font-size: 15px;
118 | color: $grey-color;
119 | margin-left: -$spacing-unit / 2;
120 | @extend %clearfix;
121 | }
122 |
123 | .footer-col {
124 | float: left;
125 | margin-bottom: $spacing-unit / 2;
126 | padding-left: $spacing-unit / 2;
127 | }
128 |
129 | .footer-col-1 {
130 | width: -webkit-calc(35% - (#{$spacing-unit} / 2));
131 | width: calc(35% - (#{$spacing-unit} / 2));
132 | }
133 |
134 | .footer-col-2 {
135 | width: -webkit-calc(20% - (#{$spacing-unit} / 2));
136 | width: calc(20% - (#{$spacing-unit} / 2));
137 | }
138 |
139 | .footer-col-3 {
140 | width: -webkit-calc(45% - (#{$spacing-unit} / 2));
141 | width: calc(45% - (#{$spacing-unit} / 2));
142 | }
143 |
144 | @include media-query($on-laptop) {
145 | .footer-col-1,
146 | .footer-col-2 {
147 | width: -webkit-calc(50% - (#{$spacing-unit} / 2));
148 | width: calc(50% - (#{$spacing-unit} / 2));
149 | }
150 |
151 | .footer-col-3 {
152 | width: -webkit-calc(100% - (#{$spacing-unit} / 2));
153 | width: calc(100% - (#{$spacing-unit} / 2));
154 | }
155 | }
156 |
157 | @include media-query($on-palm) {
158 | .footer-col {
159 | float: none;
160 | width: -webkit-calc(100% - (#{$spacing-unit} / 2));
161 | width: calc(100% - (#{$spacing-unit} / 2));
162 | }
163 | }
164 |
165 |
166 |
167 | /**
168 | * Page content
169 | */
170 | .page-content {
171 | padding: $spacing-unit 0;
172 | }
173 |
174 | .page-heading {
175 | font-size: 20px;
176 | }
177 |
178 | .post-list {
179 | margin-left: 0;
180 | list-style: none;
181 |
182 | > li {
183 | margin-bottom: $spacing-unit;
184 | }
185 | }
186 |
187 | .post-meta {
188 | font-size: $small-font-size;
189 | color: $grey-color;
190 | }
191 |
192 | .post-link {
193 | display: block;
194 | font-size: 24px;
195 | }
196 |
197 |
198 |
199 | /**
200 | * Posts
201 | */
202 | .post-header {
203 | margin-bottom: $spacing-unit;
204 | }
205 |
206 | .post-title {
207 | font-size: 42px;
208 | letter-spacing: -1px;
209 | line-height: 1;
210 |
211 | @include media-query($on-laptop) {
212 | font-size: 36px;
213 | }
214 | }
215 |
216 | .post-content {
217 | margin-bottom: $spacing-unit;
218 |
219 | h2 {
220 | font-size: 32px;
221 |
222 | @include media-query($on-laptop) {
223 | font-size: 28px;
224 | }
225 | }
226 |
227 | h3 {
228 | font-size: 26px;
229 |
230 | @include media-query($on-laptop) {
231 | font-size: 22px;
232 | }
233 | }
234 |
235 | h4 {
236 | font-size: 20px;
237 |
238 | @include media-query($on-laptop) {
239 | font-size: 18px;
240 | }
241 | }
242 | }
243 |
--------------------------------------------------------------------------------
/docs/_sass/_syntax-highlighting.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Syntax highlighting styles
3 | */
4 | .highlight {
5 | background: #fff;
6 | @extend %vertical-rhythm;
7 |
8 | .highlighter-rouge & {
9 | background: #eef;
10 | }
11 |
12 | .c { color: #998; font-style: italic } // Comment
13 | .err { color: #a61717; background-color: #e3d2d2 } // Error
14 | .k { font-weight: bold } // Keyword
15 | .o { font-weight: bold } // Operator
16 | .cm { color: #998; font-style: italic } // Comment.Multiline
17 | .cp { color: #999; font-weight: bold } // Comment.Preproc
18 | .c1 { color: #998; font-style: italic } // Comment.Single
19 | .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
20 | .gd { color: #000; background-color: #fdd } // Generic.Deleted
21 | .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
22 | .ge { font-style: italic } // Generic.Emph
23 | .gr { color: #a00 } // Generic.Error
24 | .gh { color: #999 } // Generic.Heading
25 | .gi { color: #000; background-color: #dfd } // Generic.Inserted
26 | .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
27 | .go { color: #888 } // Generic.Output
28 | .gp { color: #555 } // Generic.Prompt
29 | .gs { font-weight: bold } // Generic.Strong
30 | .gu { color: #aaa } // Generic.Subheading
31 | .gt { color: #a00 } // Generic.Traceback
32 | .kc { font-weight: bold } // Keyword.Constant
33 | .kd { font-weight: bold } // Keyword.Declaration
34 | .kp { font-weight: bold } // Keyword.Pseudo
35 | .kr { font-weight: bold } // Keyword.Reserved
36 | .kt { color: #458; font-weight: bold } // Keyword.Type
37 | .m { color: #099 } // Literal.Number
38 | .s { color: #d14 } // Literal.String
39 | .na { color: #008080 } // Name.Attribute
40 | .nb { color: #0086B3 } // Name.Builtin
41 | .nc { color: #458; font-weight: bold } // Name.Class
42 | .no { color: #008080 } // Name.Constant
43 | .ni { color: #800080 } // Name.Entity
44 | .ne { color: #900; font-weight: bold } // Name.Exception
45 | .nf { color: #900; font-weight: bold } // Name.Function
46 | .nn { color: #555 } // Name.Namespace
47 | .nt { color: #000080 } // Name.Tag
48 | .nv { color: #008080 } // Name.Variable
49 | .ow { font-weight: bold } // Operator.Word
50 | .w { color: #bbb } // Text.Whitespace
51 | .mf { color: #099 } // Literal.Number.Float
52 | .mh { color: #099 } // Literal.Number.Hex
53 | .mi { color: #099 } // Literal.Number.Integer
54 | .mo { color: #099 } // Literal.Number.Oct
55 | .sb { color: #d14 } // Literal.String.Backtick
56 | .sc { color: #d14 } // Literal.String.Char
57 | .sd { color: #d14 } // Literal.String.Doc
58 | .s2 { color: #d14 } // Literal.String.Double
59 | .se { color: #d14 } // Literal.String.Escape
60 | .sh { color: #d14 } // Literal.String.Heredoc
61 | .si { color: #d14 } // Literal.String.Interpol
62 | .sx { color: #d14 } // Literal.String.Other
63 | .sr { color: #009926 } // Literal.String.Regex
64 | .s1 { color: #d14 } // Literal.String.Single
65 | .ss { color: #990073 } // Literal.String.Symbol
66 | .bp { color: #999 } // Name.Builtin.Pseudo
67 | .vc { color: #008080 } // Name.Variable.Class
68 | .vg { color: #008080 } // Name.Variable.Global
69 | .vi { color: #008080 } // Name.Variable.Instance
70 | .il { color: #099 } // Literal.Number.Integer.Long
71 | }
72 |
--------------------------------------------------------------------------------
/docs/css/colors.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #F4F4F4;
3 | }
4 |
5 | a {
6 | color: #58585A;
7 | }
8 |
9 | .bg-white {
10 | background-color: #FFFFFF;
11 | color: #58585A;
12 | }
13 |
14 | .bg-brown {
15 | background-color: #F8F7F0;
16 | color: #58585A;
17 | }
18 |
19 | .bg-gray {
20 | background-color: #58585A;
21 | color: #FFFFFF;
22 | }
23 |
24 | .bg-red {
25 | background-color: #C92C1E;
26 | color: #FFFFFF;
27 | }
28 |
29 | .bg-red-hover:hover {
30 | background-color: #C92C1E;
31 | color: #FFFFFF;
32 | }
33 |
34 | .bg-blue {
35 | background-color: #2879CB;
36 | color: #FFFFFF;
37 | }
38 |
39 | .bg-blue-hover:hover {
40 | background-color: #2879CB;
41 | color: #FFFFFF;
42 | }
43 |
44 | .bg-dark-brown {
45 | background-color: #E8E3CE;
46 | color: #58585A;
47 | }
--------------------------------------------------------------------------------
/docs/css/components.css:
--------------------------------------------------------------------------------
1 | .button {
2 | display: inline-block;
3 |
4 | padding: 10px;
5 | margin-top: 15px;
6 |
7 | border-radius: 30px;
8 |
9 | font-size: 16px;
10 | line-height: 16px;
11 |
12 | text-decoration: none;
13 |
14 | transition: all .5s;
15 | }
16 |
17 | .button:hover {
18 | box-shadow: 2px 2px 5px #888888;
19 | }
20 |
21 | .header-button {
22 | display: block;
23 |
24 | font-size: 20px;
25 | line-height: 35px;
26 |
27 | text-align: center;
28 | text-decoration: none;
29 |
30 | transition: all .5s;
31 | }
32 |
33 | .new-decorator {
34 | position: absolute;
35 | width: 100px;
36 | height: 100px;
37 | margin-left: -7px;
38 | margin-top: -5px;
39 | }
40 |
41 | .socials {
42 | display: flex;
43 | }
44 |
45 | .socials a {
46 | display: inline-block;
47 | width: 28px;
48 | height: 28px;
49 | overflow: hidden;
50 | text-indent: -999px;
51 | background: url(img/socials.png) 0 0 no-repeat;
52 | }
53 |
54 | .socials a#f-fb {
55 | background-position: 0 -50px;
56 | }
57 | .socials a#f-tw {
58 | background-position: 0 -73px;
59 | }
60 | .socials a#f-ln {
61 | background-position: 0 -97px;
62 | }
63 | .socials a#f-gp {
64 | background-position: 0 -123px;
65 | }
66 | .socials a#f-rss {
67 | background-position: 0 -150px;
68 | }
69 |
70 | @media all and (max-width: 599px) {
71 | .button {
72 | display: block;
73 | margin: 30px 50px;
74 | padding: 20px;
75 |
76 | text-align: center;
77 | }
78 | }
--------------------------------------------------------------------------------
/docs/css/defaults.css:
--------------------------------------------------------------------------------
1 | html, body, div, p, ul, ol, li, h1, h2, h3, h4, h5, h6 {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-size:10px;
8 | line-height:10px;
9 | }
10 |
11 | h1, h2, h3, h4, h5, h6 {
12 | font-family: "Roboto", sans-serif;
13 | }
14 |
15 |
16 | h1 {
17 | font-size: 28px;
18 | line-height: 32px;
19 |
20 | margin-bottom: 24px;
21 | }
22 |
23 | h2 {
24 | font-size: 24px;
25 | line-height: 28px;
26 |
27 | margin-bottom: 20px;
28 | }
29 |
30 | h3 {
31 | font-size: 20px;
32 | line-height: 24px;
33 |
34 | margin-bottom: 16px;
35 | }
36 |
37 | p {
38 | font-size: 16px;
39 | line-height: 20px;
40 |
41 | font-family: Georgia, Arial, sans-serif;
42 | }
43 |
--------------------------------------------------------------------------------
/docs/css/elements.css:
--------------------------------------------------------------------------------
1 | #header {
2 | position: relative;
3 | z-index: 2;
4 | }
5 |
6 | #header #menu {
7 | position: absolute;
8 |
9 | width: 100%;
10 |
11 | top: 0;
12 | left: 0;
13 |
14 | transition: 1s all;
15 | }
16 |
17 | #header #hero {
18 | padding-top: 130px;
19 |
20 | text-align: center;
21 | }
22 |
23 | #content {
24 | position: relative;
25 | z-index: 1;
26 | }
27 |
28 | #footer {
29 | position: relative;
30 | z-index: 1;
31 |
32 | text-align: center;
33 | }
--------------------------------------------------------------------------------
/docs/css/images.css:
--------------------------------------------------------------------------------
1 | img {
2 | width: 100%;
3 | height: auto;
4 |
5 | display: block;
6 |
7 | margin: 0;
8 | }
9 |
10 | .w200 {
11 | max-width: 200px;
12 | }
13 |
14 | @media all and (max-width: 599px) {
15 | .w200 {
16 | margin-bottom: 20px;
17 | margin-left: auto;
18 | margin-right: auto;
19 | }
20 | }
--------------------------------------------------------------------------------
/docs/css/img/socials.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EDMdesigner/textversionjs/1f53cbb97db4b1ca2d297e600f4253578b884740/docs/css/img/socials.png
--------------------------------------------------------------------------------
/docs/css/layout.css:
--------------------------------------------------------------------------------
1 | .container600 {
2 | width: 600px;
3 | margin: 0 auto;
4 | }
5 |
6 | .container800 {
7 | width: 800px;
8 | margin: 0 auto;
9 | }
10 |
11 | .cols > .w33p {
12 | width: 33.33%;
13 | float: left;
14 | }
15 |
16 | .cols > .w66p {
17 | width: 66.66%;
18 | float: left;
19 | }
20 |
21 | .cols > .w50p {
22 | width: 50%;
23 | float: left;
24 | }
25 |
26 | .cols > .w25p {
27 | width: 25%;
28 | float: left;
29 | }
30 |
31 | .cols > .w20p {
32 | width: 20%;
33 | flex-grow: 1;
34 | }
35 |
36 | .cols:after {
37 | content: "";
38 | display: block;
39 | clear: both;
40 | }
41 |
42 | .cols-r > .w33p {
43 | width: 33.33%;
44 | float: right;
45 | }
46 |
47 | .cols-r > .w66p {
48 | width: 66.66%;
49 | float: right;
50 | }
51 |
52 | .cols-r > .w50p {
53 | width: 50%;
54 | float: right;
55 | }
56 |
57 | .cols-r > .w25p {
58 | width: 25%;
59 | float: right;
60 | }
61 |
62 | .cols-r > .w20p {
63 | width: 20%;
64 | float: right;
65 | }
66 |
67 | .cols-r:after {
68 | content: "";
69 | display: block;
70 | clear: both;
71 | }
72 |
73 | .clr {
74 | clear: both;
75 | }
76 |
77 | @media all and (max-width: 799px) {
78 | .container800 {
79 | width: 100%;
80 | }
81 | }
82 |
83 | @media all and (max-width: 599px) {
84 | .container600 {
85 | width: 100%;
86 | }
87 |
88 | .reorder > .w33p {
89 | width: 100%;
90 | }
91 |
92 | .reorder > .w66p {
93 | width: 100%;
94 | }
95 |
96 | .reorder > .w50p {
97 | width: 100%;
98 | }
99 |
100 | .reorder > .w25p {
101 | width: 100%;
102 | }
103 |
104 | .reorder > .w20p {
105 | width: 100%;
106 | }
107 | }
--------------------------------------------------------------------------------
/docs/css/main.scss:
--------------------------------------------------------------------------------
1 | ---
2 | # Only the main Sass file needs front matter (the dashes are enough)
3 | ---
4 | @charset "utf-8";
5 |
6 |
7 |
8 | // Our variables
9 | $base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
10 | $base-font-size: 16px;
11 | $base-font-weight: 400;
12 | $small-font-size: $base-font-size * 0.875;
13 | $base-line-height: 1.5;
14 |
15 | $spacing-unit: 30px;
16 |
17 | $text-color: #111;
18 | $background-color: #fdfdfd;
19 | $brand-color: #58585A;
20 |
21 | $grey-color: #828282;
22 | $grey-color-light: lighten($grey-color, 40%);
23 | $grey-color-dark: darken($grey-color, 25%);
24 |
25 | // Width of the content area
26 | $content-width: 800px;
27 |
28 | $on-palm: 600px;
29 | $on-laptop: 800px;
30 |
31 |
32 |
33 | // Use media queries like this:
34 | // @include media-query($on-palm) {
35 | // .wrapper {
36 | // padding-right: $spacing-unit / 2;
37 | // padding-left: $spacing-unit / 2;
38 | // }
39 | // }
40 | @mixin media-query($device) {
41 | @media screen and (max-width: $device) {
42 | @content;
43 | }
44 | }
45 |
46 |
47 |
48 | // Import partials from `sass_dir` (defaults to `_sass`)
49 | @import
50 | "base",
51 | "layout",
52 | "syntax-highlighting"
53 | ;
54 |
55 | textarea {
56 | width: 100%;
57 | height: 300px;
58 | }
--------------------------------------------------------------------------------
/docs/css/spacings.css:
--------------------------------------------------------------------------------
1 | .sm-padding {
2 | padding: 10px;
3 | }
4 |
5 | .sm-padding-tb {
6 | padding-top: 10px;
7 | padding-bottom: 10px;
8 | }
9 |
10 | .m-padding-tb {
11 | padding-top: 30px;
12 | padding-bottom: 30px;
13 | }
14 |
15 | .l-padding-tb {
16 | padding-top: 100px;
17 | padding-bottom: 100px;
18 | }
19 |
--------------------------------------------------------------------------------
/docs/documentation.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Documentation
4 | permalink: /documentation/
5 | ---
6 |
7 | # textversionjs
8 |
9 | Generate the text version of your HTML email in a second.
10 |
11 | This tool is an open source project. Feel free to use it any time in your projects!
12 |
13 | ## htmlToPlainText
14 |
15 | The function that generates plain text from email htmls.
16 |
17 | ### Params
18 |
19 | Param | Type | Required | Default value | Description
20 | --- |--- |--- |--- |---
21 | htmlText | string | Yes | | The html version of the email
22 | styleConfig | json | No | | Options for converting
23 |
24 | ### styleConfig
25 |
26 | Param | Type | Required | Default value | Description
27 | --- |--- |--- |--- |---
28 | linkProcess | function | No | | Callback function to customize links appearance
29 | imgProcess | function | No | | Callback function to customize image appearance
30 | headingStyle | string | No | "underline" | Define heading appearance, options: "underline", "linebreak", "hashify"
31 | listStyle | string | No | "indention" | Define list appearance, options: "indention", "linebreak"
32 | uIndentionChar | string | No | "-" | If listStyle is indention, uIndentionChar is the character that fills the indention for unordered lists
33 | oIndentionChar | string | No | "-" | If listStyle is indention, oIndentionChar is the character that fills the indention for ordered lists after the heading number
34 | listIndentionTabs | int | No | 3 | If listStyle is indention, listIndentionTabs is the width of the indention
35 |
36 | ### linkProcess
37 |
38 | Param | Type | Required | Default value | Description
39 | --- |--- |--- |--- |---
40 | href | string | Yes | | The destination (href property) of the link
41 | linkText | string | Yes | | The text of the link
42 |
43 | ### imgProcess
44 |
45 | Param | Type | Required | Default value | Description
46 | --- |--- |--- |--- |---
47 | src | string | Yes | | The source (src property) of the image
48 | alt | string | Yes | | The alternative text (alt property) of the image
49 |
50 | ### Examples
51 |
52 | #### Simple conversion with default style
53 |
54 | ```js
55 | var textVersion = require("textversionjs");
56 | var htmlText = "" +
57 | "" +
58 | "Lorem ipsum dolor sic amet " +
59 | "Lorem ipsum sic amet " +
60 | "Lorem ipsum dolor sic amet
" +
61 | "" +
64 | "" +
65 | "";
66 |
67 | var plainText = textVersion(htmlText);
68 | // returns
69 | // "Lorem ipsum [dolor] (http://foo.foo) sic amet
70 | // Lorem ipsum ![foo] (http://foo.jpg) sic amet
71 | // Lorem ipsum dolor
72 | // sic amet"
73 |
74 | ```
75 |
76 | #### Customize link appearance
77 |
78 | ```js
79 | var textVersion = require("textversionjs");
80 | var htmlText = "Lorem ipsum dolor sic amet
";
81 |
82 | var styleConfig: {
83 | linkStyle: function(href, linkText){
84 | return linkText + " " + "(" + href + ")";
85 | }
86 | };
87 |
88 | var plainText = textVersion(htmlText, styleConfig);
89 | // returns "Lorem ipsum (http://foo.foo) dolor sic amet"
90 |
91 | ```
92 |
93 | #### Customize headings
94 |
95 | ```js
96 | var textVersion = require("textversionjs");
97 |
98 | var htmlText = "Lorem ipsum " +
99 | "Lorem ipsum dolor sic amet
";
100 |
101 | var styleConfig: {
102 | headingStyle: "hashify"
103 | };
104 |
105 | var plainText = textVersion(htmlText, styleConfig);
106 | // returns
107 | // "# Lorem ipsum
108 | //
109 | // Lorem ipsum dolor sic amet"
110 |
111 | ```
112 |
113 | #### Customize lists
114 |
115 | ```js
116 | var textVersion = require("textversionjs");
117 | var htmlText = "" +
118 | "Lorem " +
119 | "ipsum " +
120 | " " +
121 | "" +
122 | "Lorem " +
123 | "ipsum " +
124 | " ";
125 |
126 | var styleConfig: {
127 | headingStyle: "indention",
128 | uIndentionChar: ".";
129 | listIndentionTabs: 2;
130 | };
131 |
132 | var plainText = textVersion(htmlText, styleConfig);
133 | // returns "
134 | // ..Lorem
135 | // ..ipsum
136 | // 3.Lorem
137 | // 4.ipsum"
138 | ```
139 |
140 | Try it online in our [Demo page](http://emailtextversion.com/)!
141 |
142 | Don't forget to check out our other open source projects at [EDMdesigner](http://edmdesigner.com/).
143 |
144 | Follow us on [github](https://github.com/EDMdesigner) and [twitter](https://twitter.com/EDMdesigner)!
--------------------------------------------------------------------------------
/docs/feed.xml:
--------------------------------------------------------------------------------
1 | ---
2 | layout: null
3 | ---
4 |
5 |
6 |
7 | {{ site.title | xml_escape }}
8 | {{ site.description | xml_escape }}
9 | {{ site.url }}{{ site.baseurl }}/
10 |
11 | {{ site.time | date_to_rfc822 }}
12 | {{ site.time | date_to_rfc822 }}
13 | Jekyll v{{ jekyll.version }}
14 | {% for post in site.posts limit:10 %}
15 | -
16 |
{{ post.title | xml_escape }}
17 | {{ post.content | xml_escape }}
18 | {{ post.date | date_to_rfc822 }}
19 | {{ post.url | prepend: site.baseurl | prepend: site.url }}
20 | {{ post.url | prepend: site.baseurl | prepend: site.url }}
21 | {% for tag in post.tags %}
22 | {{ tag | xml_escape }}
23 | {% endfor %}
24 | {% for cat in post.categories %}
25 | {{ cat | xml_escape }}
26 | {% endfor %}
27 |
28 | {% endfor %}
29 |
30 |
31 |
--------------------------------------------------------------------------------
/docs/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EDMdesigner/textversionjs/1f53cbb97db4b1ca2d297e600f4253578b884740/docs/img/logo.png
--------------------------------------------------------------------------------
/docs/img/socials.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EDMdesigner/textversionjs/1f53cbb97db4b1ca2d297e600f4253578b884740/docs/img/socials.png
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | ---
4 |
5 |
6 |
7 |
TextVersionJS
8 |
9 |
{{ site.description }}
10 |
This tool is based on the TextVersionJS open source project. Feel free to use it any time in your projects!
11 |
12 |
HTML to plain text converter online
13 |
14 |
You just have to copy & paste your email HTML code in the first textarea and press the generate button.
15 |
16 |
Paste your email HTML here
17 |
18 |
19 |
20 |
21 |
Generate
22 |
23 |
24 |
The text version
25 |
26 |
27 |
28 |
29 |
39 |
40 |
--------------------------------------------------------------------------------
/docs/js/textversion.js:
--------------------------------------------------------------------------------
1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.textversion = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o tags including the tag itself
54 | tmp = tmp.replace(/<\/body>.*/i, "");
55 | tmp = tmp.replace(/.*]*>/i, "");
56 |
57 | // remove inbody scripts and styles
58 | tmp = tmp.replace(/<(script|style)( [^>]*)*>((?!<\/\1( [^>]*)*>).)*<\/\1>/gi, "");
59 |
60 | // remove all tags except that are being handled separately
61 | tmp = tmp.replace(/<(\/)?((?!h[1-6]( [^>]*)*>)(?!img( [^>]*)*>)(?!a( [^>]*)*>)(?!ul( [^>]*)*>)(?!ol( [^>]*)*>)(?!li( [^>]*)*>)(?!p( [^>]*)*>)(?!div( [^>]*)*>)(?!td( [^>]*)*>)(?!br( [^>]*)*>)[^>\/])[^>]*>/gi, "");
62 |
63 | // remove or replace images - replacement texts with <> tags will be removed also, if not intentional, try to use other notation
64 | tmp = tmp.replace(/ ]*)>/gi, function (str, imAttrs) {
65 | var imSrc = "";
66 | var imAlt = "";
67 | var imSrcResult = /src="([^"]*)"/i.exec(imAttrs);
68 | var imAltResult = /alt="([^"]*)"/i.exec(imAttrs);
69 | if (imSrcResult !== null) {
70 | imSrc = imSrcResult[1];
71 | }
72 | if (imAltResult !== null) {
73 | imAlt = imAltResult[1];
74 | }
75 | if (typeof imgProcess === "function") {
76 | return imgProcess(imSrc, imAlt);
77 | }
78 | if (imAlt === "") {
79 | return "![image] (" + imSrc + ")";
80 | }
81 | return "![" + imAlt + "] (" + imSrc + ")";
82 | });
83 |
84 | function createListReplaceCb() {
85 | return function (match, listType, listAttributes, listBody) {
86 | var liIndex = 0;
87 | if (listAttributes && /start="([0-9]+)"/i.test(listAttributes)) {
88 | liIndex = /start="([0-9]+)"/i.exec(listAttributes)[1] - 1;
89 | }
90 | var plainListItem = "" + listBody.replace(/
]*>(((?! ]*>)(?!<\/li>).)*)<\/li>/gi, function (str, listItem) {
91 | var actSubIndex = 0;
92 | var plainListLine = listItem.replace(/(^|( ))(?!)/gi, function () {
93 | if (listType === "o" && actSubIndex === 0) {
94 | liIndex += 1;
95 | actSubIndex += 1;
96 | return " " + liIndex + populateChar(oIndentionChar, listIndentionTabs - String(liIndex).length);
97 | }
98 | return " " + uIndention;
99 | });
100 | return plainListLine;
101 | }) + "
";
102 | return plainListItem;
103 | };
104 | }
105 |
106 | // handle lists
107 | if (listStyle === "linebreak") {
108 | tmp = tmp.replace(/<\/?ul[^>]*>|<\/?ol[^>]*>|<\/?li[^>]*>/gi, "\n");
109 | } else if (listStyle === "indention") {
110 | while (/<(o|u)l[^>]*>(.*)<\/\1l>/gi.test(tmp)) {
111 | tmp = tmp.replace(/<(o|u)l([^>]*)>(((?!<(o|u)l[^>]*>)(?!<\/(o|u)l>).)*)<\/\1l>/gi, createListReplaceCb());
112 | }
113 | }
114 |
115 | // handle headings
116 | if (headingStyle === "linebreak") {
117 | tmp = tmp.replace(/]*>([^<]*)<\/h\1>/gi, "\n$2\n");
118 | } else if (headingStyle === "underline") {
119 | tmp = tmp.replace(/