Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parser refactor #43

Merged
merged 42 commits into from
Feb 10, 2017
Merged

Parser refactor #43

merged 42 commits into from
Feb 10, 2017

Conversation

gdolle
Copy link
Contributor

@gdolle gdolle commented Jan 23, 2017

Major refactoring for the parser. Breaking changes (3.1.0 ?)

Changelog

  • Fix options bugs (random behaviour between book.json and local command, ace plugin does not support quotes in command options)
  • Add Url support Parsing code from URL (Feature) #42 (sync http request using sync-request modules + check url valid-url)
  • Refactor options using immutable maps (more robust). It makes easier future new options, see src/options.js
  • Support real types (not retrocompatible for book options). For example edit:true instead of edit:"true", to be more consistent (this fix an ace plugin bug).
  • Add parser checks for types.
  • Add different warn level.
  • template, fixlang, lang, theme are now also local/global options. We can set a template per code, a theme per code, etc.. or globally.
  • Refactor test for these last changes.
  • Add new tests for URL
  • End support of lang-typescript to use uniform options lang:"typescript" to be consistent with other options and to simplify functions.
  • Support multiple snippet codes. Now we can do [import:"tag0,tag1,..."](fixtures/test.js) to import several snippets into one codeblock , for example
//! [tag0]
int a;
//! [tag0]
// A comment or a code
//! [tag1]
int b;
//! [tag1]

will produce

int a;
int b;

It should work far better with this PR :)

I've been noticed that ace plugin might crash after a page reload in previous version, but I couldn't reproduce that problem. However, these changes fix some bugs and "might" be fix for that behaviour, we will see.

NB: It might be interesting to have a look to async operation in the future to optimize the code.

@azu waiting for your review, you'll have some work ;)

Not required in fact.

`gitbook-plugin-ace` is required only if user pass "ace" or "acefull" to the template
option. It is specified in the README.md.
- Add winston-color for color logs
- produce a warning if gitbook-plugin-ace is not loaded (ace template won't work)
- produce an error if gitbook-plugin-ace is loaded but before include-codeblock
- Should be cleaner and less error prone
- Define global book option map, and possible key-value map (same as in
  readme).
- Use immutable Map to avoid unwanted changes.
- Pass `template`, `unindent` function arguments into the key-value map
  directly for consistency.
- Systemize key-value argument for each functions.
- include-codeblock does not work if we use it inline.
for example:

```
blabla [import](fixtures/test.js) blablabla
```

NB: we might have some works to add newline before and after block.
- It seems ace does work with boolean instead of strings for booleans
type keys.
- Update version 3.1.0, changes will be major
Options can be set globally or locally:

- Set an immutable default map book.json global plugin options
- Set an immutable default key-value map for local command options.
- Add functions to check map types
- Refactor parseVariableFromCommand regex to be more comprehensible.
- Handle boolean type
- Add parse check depending on the value type and convert the parsed
  value to its type (JSON.parse)
- Fix type check. Default l/g options map should not have `undefined`
  value as value type is deduced from the map.
- Update check for empty string which is not valid.
- Add default value options in package.json directly. Options map are
  updated from it.
- Fix package default type to be consistent (avoid string). Now boolean
  is `true` and not `"true"`.
break backward compatibility

- set hardcode lang as book option, or command option.
- Remove `lang-javascript` and use standard key-val format
`lang:"javascript"` or `lang:".js"`. If lang or extension (via lang) is not set,
 then lang is determined rom file extension.
- Create template.js file for template specific codes.
issue azu#42

- Perform http GET request and retrieve url body.
- Asynchronous http (module sync-request) with caching, gzip
- Redirection not allowed.

NB: Future optimization could be to provide async operation for the
plugin.
@azu
Copy link
Owner

azu commented Jan 23, 2017

Oh, large diff..
I'll look it lator.
Can you separate refactor PR and feature PR if possible.

@azu azu self-requested a review January 23, 2017 09:34
src/parser.js Outdated
* @param {string} originalPath
* @return {string}
*/
export function getContent( filePath, originalPath )
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of feature #42

@@ -1,5 +1,5 @@
{% if file.type=="asciidoc" %}++++{% endif %}
{%ace edit="{{edit}}", check="{{check}}", theme="{{theme}}", lang="{{lang}}" %}
{%ace edit={{edit}}, check={{check}}, theme="{{theme}}", lang="{{lang}}" %}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major bug fix here

@gdolle
Copy link
Contributor Author

gdolle commented Jan 23, 2017

@azu Actually, features are minors and deeply dependent of the of refactor. It'd be quite difficult to separate now.

Would it be ok to keep it as one PR ?

The related features changes are

  • multiple markers (parseVariableFromLabel => change the regex to have several comma ~1line)
  • URL parser ( getContent => load url or file ~5lines)
  • the 1 tests for each in test-parser.js

(I added comments on file changes to help)

@azu
Copy link
Owner

azu commented Jan 24, 2017

@gdolle fmm, I want to separate big PR to smll PRs by following reasons.

Add Url support #42 (sync http request using sync-request modules + check url valid-url)

Sync request is simple solution, but it is not correct solution.
Because GitBook support async hook.

(Not actuall code)

// THIS IS IMAGINE
module.exports = {
    hooks: {
        "page:before": function(page) {
            var options = this.options.pluginsConfig["include-codeblock"];
            var pageDir = path.dirname(page.rawPath);
            var parseResults = parse(page.content, pageDir, options);
            var promises = results.map(result => {
                return requestUrlAndCreateReplaceContent(result).then(newContent => {
                     replaceContent(page, newContent);
                });
            });
            return Promise.all(promises); // GitBook support async by returing promise
        }
    }
};

and

Immutable.js is overlarge for this project.
I recommened that use ES2015 Map + Poilyfill insteadof immutable.js.


Of course, Welcome to bugfix, but the bugfix should not contains other feature.
I hesitate to merge the bugfix PR.

Sorry, slow response.

@gdolle
Copy link
Contributor Author

gdolle commented Jan 24, 2017

Does ES2015 Map guaranty const Map values ?

Actually refactor parser:

  1. immutable Map for read only (more robust to my opinion)
  2. handle key-val types (boolean, string, number). The "bug fix" is a consequence of the parser refactor (maybe my single comment is error prone) it's not really a feature.

I agree for the url feature, it is from far not perfect. I'll separate it in another PR.

Copy link
Owner

@azu azu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does ES2015 Map guaranty const Map values ?

Yes and No.

Immutable.js is great library, but it is not first class in JavaScript.
In other word, When other constributor see the code that includes immutable.js, they have to learn about immutable.js. I think that it contains cost.

I've written some Map examples.

If you actualy want to use immutable.js, I can't prevent it.

I agree for the url feature, it is from far not perfect. I'll separate it in another PR.

Ok.

src/parser.js Outdated
const spaces_ex = "\\s*";
const quotes_ex = "[\"']";

Object.keys(kv).forEach(key => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can ES2015 Map does same thing?

const resultMap = new Map();
kvMap.forEach(key => { 
   // something
   resultMap.set(key, foo);
}
return resultMap;

src/parser.js Outdated
const kv = kvMap.toObject();
const count = hasTitle(kv) ? codeCounter() : -1;
checkMapTypes( kvMap, "generatedEmbedCode" );
const contextMap = kvMap.concat( immutable.Map({
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var mergedMap = new Map([...kvMap, ...otherMap])

var a = new Map([["k1", "v1"], ["k2", "v2"]]);
var b = new Map([["k3", "v3"], ["k4", "v4"]]);
var mergedMap = new Map([...a, ...b]);
console.log(mergedMap); // Map { k1: "v1", k2: "v2", k3: "v3", k4: "v4" }
// Object to Map
new Map(Object.entries({ k : 1 }))

@azu
Copy link
Owner

azu commented Jan 25, 2017

(Currently, this project mixed codeing style, We should apply ESLint #39)

- Remove immutable package
- Remove Map object to use frozen Object instead (guaranty unmodified
  default map object).
- Update tests.
- Remove URL parser source code (different branch + need update async)
- Remove URL parser test
- Remove package.json dependencies
@gdolle
Copy link
Contributor Author

gdolle commented Jan 29, 2017

@azu I updated the code.

  • Remove immutable: I used object instead of Map and froze object that should be immutable. It should be understandable for future contributors.
  • Remove URL feature.

I didn't apply yet Eslint, I'll have a look into that.

See issue azu#39

- Use this convention https://github.com/textlint/textlint/blob/master/.eslintrc.js
- Change Error to Warn for unused vars and allow console logs.
- Add new package script : check => run eslint for javascript files in src/ and test/.
  (Do not add test/fixtures, test/patterns, ...).
- Add travis eslint check.
@gdolle
Copy link
Contributor Author

gdolle commented Jan 30, 2017

@azu I added eslint config following #39 and fix current code following the convention.
I also added a "check" script which test eslint on src/ and test/.
This script is executed in travis, therefore we can see if something is not good with respect to the coding style.
Let me know if it's ok for you like that. ;)

Copy link
Owner

@azu azu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.
I've leave some comments

src/parser.js Outdated
// inspired from https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/string/strip.rb
if((s === undefined) || (s === "")) {
return s;
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you format indent or Run $(npm bin)/eslint --fix src/ test/?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird eslint does not fix this lines..

break;
default:
logger.error("include-codeblock: parseVariablesFromLabel: key type `" +
typeof defaultKeyValueMap[key] + "` unknown (see options.js)");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add breaK; to default: block.

src/parser.js Outdated
content = removeMarkers(markerSliceCode(code, marker));
}
if (unindent || keyValueObject.unindent) {
content = strip(content);
if (unindent == true) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use === insteadof ==.

OR

const unindent = kvm.unindent !== undefined ? kvm.unindent : false;
...
if (unindent) { ... }
...

package.json Outdated
@@ -11,7 +11,7 @@
"bugs": {
"url": "https://github.com/azu/gitbook-plugin-include-codeblock/issues"
},
"version": "3.0.1",
"version": "3.1.0",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR is not include bump version.

package.json Outdated
@@ -24,6 +24,7 @@
},
"scripts": {
"build": "NODE_ENV=production babel src --out-dir lib --source-maps",
"check": "eslint src/*.js test/*.js",
"watch": "babel src --out-dir lib --watch --source-maps",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, lint command is meaningful.

Also, To define "lint:fix": "eslint --fix src/*.js test/*.js" is useful.

@gdolle
Copy link
Contributor Author

gdolle commented Feb 9, 2017

Sorry for the late reply. I updated the code relatively to your last review

@azu azu merged commit ce64163 into azu:master Feb 10, 2017
@azu
Copy link
Owner

azu commented Feb 10, 2017

@gdolle Thanks for great work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants