Skip to content

Commit 8eb1280

Browse files
committed
feat: create new html and xhtml files with default content and NewFileContentManager feature
1 parent 334887d commit 8eb1280

19 files changed

Lines changed: 484 additions & 22 deletions

docs/generatedApiDocs/GitHub-API-Index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
The list of all APIs for phoenix.
33

44
1. [features/BeautificationManager](BeautificationManager-API)
5+
1. [features/NewFileContentManager](NewFileContentManager-API)
56
1. [features/QuickViewManager](QuickViewManager-API)
67
1. [features/SelectionViewManager](SelectionViewManager-API)
78
1. [utils/EventDispatcher](EventDispatcher-API)
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
2+
3+
## features/NewFileContentManager
4+
5+
NewFileContentManager provides support to add default template content when a new/empty file is created.
6+
Extensions can register to provide content with `NewFileContentManager.registerContentProvider` API.
7+
8+
## Usage
9+
10+
Let's say whenever a user creates a new js file, we have to prefill the contents to "console.log("hello")"
11+
12+
```js
13+
const NewFileContentManager = brackets.getModule("features/NewFileContentManager");
14+
// replace `js` with language ID(Eg. javascript) if you want to restrict the preview to js files only. use `all` for
15+
// all languages.
16+
NewFileContentManager.registerContentProvider(exports, ["js"], 1);
17+
18+
// provide a helpful name for the ContentProvider. This will be useful if you have to debug.
19+
exports.CONTENT_PROVIDER_NAME = "extension.someName";
20+
// now implement the getContent function that will be invoked when ever creates a new empty file.
21+
exports.getContent = function(fullPath) {
22+
return new Promise((resolve, reject)=>{
23+
resolve("sample content");
24+
});
25+
};
26+
```
27+
28+
## API
29+
30+
### registerContentProvider
31+
32+
Register a Content provider with this api.
33+
34+
```js
35+
// syntax
36+
NewFileContentManager.registerContentProvider(provider, supportedLanguages, priority);
37+
```
38+
39+
The API requires three parameters:
40+
41+
1. `provider`: must implement a `getContent` function which will be invoked to get the content. See API doc below.
42+
2. `supportedLanguages`: An array of languages that the provider supports. If `["all"]` is supplied, then the
43+
provider will be invoked for all languages. Restrict to specific languages: Eg: `["javascript", "html", "php"]`
44+
3. `priority`: Contents provided hy providers with higher priority will win if there are more than
45+
one provider registered for the language. Default is 0.
46+
47+
```js
48+
// to register a provider that will be invoked for all languages. where provider is any object that implements
49+
// a getContent function
50+
NewFileContentManager.registerContentProvider(provider, ["all"]);
51+
52+
// to register a provider that will be invoked for specific languages
53+
NewFileContentManager.registerContentProvider(provider, ["javascript", "html", "php"]);
54+
```
55+
56+
### removeContentProvider
57+
58+
Removes a registered content provider. The API takes the same arguments as `registerContentProvider`.
59+
60+
```js
61+
// syntax
62+
NewFileContentManager.removeContentProvider(provider, supportedLanguages);
63+
// Example
64+
NewFileContentManager.removeContentProvider(provider, ["javascript", "html"]);
65+
```
66+
67+
### provider.getContent
68+
69+
Each provider must implement the `getContent` function that returns a promise. The promise either resolves with
70+
the content text or rejects if there is no content made available by the provider.
71+
72+
```js
73+
exports.CONTENT_PROVIDER_NAME = "extension.someName"; // for debugging
74+
// function signature
75+
exports.getContent = function(fullPath) {
76+
return new Promise((resolve, reject)=>{
77+
resolve("sample content");
78+
});
79+
};
80+
```
81+
82+
#### parameters
83+
84+
The function will be called with the path of the file that needs the content.
85+
86+
1. `fullPath` - string path
87+
88+
#### return types
89+
90+
A promise that resolves with the content text or rejects if there is no content made available by the provider.
91+
92+
## getInitialContentForFile
93+
94+
Returns a promise that resolves to the default text content of the given file after querying
95+
all the content providers. If no text is returned by any providers, it will return an empty string "".
96+
97+
### Parameters
98+
99+
* `fullPath`
100+
101+
Returns **[Promise][1]<[string][2]>** The text contents
102+
103+
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
104+
105+
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String

docs/generatedApiDocs/features/QuickViewManager-API.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ QuickViewManager.registerQuickViewProvider(provider, ["javascript", "html", "php
8484

8585
### removeQuickViewProvider
8686

87-
Removes a registered code hint provider. The API takes the same arguments as `registerQuickViewProvider`.
87+
Removes a registered QuickView provider. The API takes the same arguments as `registerQuickViewProvider`.
8888

8989
```js
9090
// syntax

docs/generatedApiDocs/features/SelectionViewManager-API.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ SelectionViewManager.registerSelectionViewProvider(provider, ["javascript", "htm
7777

7878
### removeSelectionViewProvider
7979

80-
Removes a registered code hint provider. The API takes the same arguments as `registerSelectionViewProvider`.
80+
Removes a registered SelectionView provider. The API takes the same arguments as `registerSelectionViewProvider`.
8181

8282
```js
8383
// syntax

gulpfile.js/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ function _listFilesInDir(dir) {
262262
});
263263
}
264264

265-
const ALLOWED_EXTENSIONS_TO_CACHE = ["js", "html", "htm", "css", "less", "scss", "ttf", "woff", "woff2", "eot",
265+
const ALLOWED_EXTENSIONS_TO_CACHE = ["js", "html", "htm", "xhtml", "css", "less", "scss", "ttf", "woff", "woff2", "eot",
266266
"txt", "otf",
267267
"json", "config",
268268
"zip",

src/brackets.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ define(function (require, exports, module) {
182182
require("features/QuickViewManager");
183183
require("features/SelectionViewManager");
184184
require("features/BeautificationManager");
185+
require("features/NewFileContentManager");
185186

186187
// Load modules that self-register and just need to get included in the main project
187188
require("command/DefaultMenus");

src/document/DocumentCommandHandlers.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ define(function (require, exports, module) {
5555
StatusBar = require("widgets/StatusBar"),
5656
WorkspaceManager = require("view/WorkspaceManager"),
5757
LanguageManager = require("language/LanguageManager"),
58+
NewFileContentManager = require("features/NewFileContentManager"),
5859
_ = require("thirdparty/lodash");
5960

6061
/**
@@ -758,6 +759,15 @@ define(function (require, exports, module) {
758759
// of validating file name, creating the new file and selecting.
759760
function createWithSuggestedName(suggestedName) {
760761
return ProjectManager.createNewItem(baseDirEntry, suggestedName, false, isFolder)
762+
.done(function (file) {
763+
DocumentManager.getDocumentForPath(file.fullPath)
764+
.done(doc =>{
765+
NewFileContentManager.getInitialContentForFile(file.fullPath).then(content =>{
766+
doc.setText(content);
767+
});
768+
})
769+
.fail(console.error);
770+
})
761771
.always(function () { fileNewInProgress = false; });
762772
}
763773

src/extensions/default/HTMLCodeHints/integ-tests.js

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919
*
2020
*/
2121

22-
/*global describe, it, expect, beforeAll, afterAll, awaitsForDone, awaitsForFail */
22+
/*global describe, it, expect, beforeAll, afterAll, awaitsForDone, awaitsForFail, awaits, awaitsFor */
2323

2424
define(function (require, exports, module) {
2525
// Recommended to avoid reloading the integration test window Phoenix instance for each test.
2626

27-
const SpecRunnerUtils = brackets.getModule("spec/SpecRunnerUtils");
27+
const SpecRunnerUtils = brackets.getModule("spec/SpecRunnerUtils"),
28+
KeyEvent = brackets.getModule("utils/KeyEvent");
2829

2930
describe("integration:HTML Code Hints integration tests", function () {
3031

@@ -37,18 +38,22 @@ define(function (require, exports, module) {
3738
testWindow,
3839
EditorManager,
3940
MainViewManager,
40-
brackets;
41+
brackets,
42+
FileSystem,
43+
$;
4144

4245

4346
beforeAll(async function () {
4447
testWindow = await SpecRunnerUtils.createTestWindowAndRun();
4548
brackets = testWindow.brackets;
49+
$ = testWindow.$;
4650
FileViewController = brackets.test.FileViewController;
4751
ProjectManager = brackets.test.ProjectManager;
4852
CommandManager = brackets.test.CommandManager;
4953
Commands = brackets.test.Commands;
5054
EditorManager = brackets.test.EditorManager;
5155
MainViewManager = brackets.test.MainViewManager;
56+
FileSystem = brackets.test.FileSystem;
5257

5358
await SpecRunnerUtils.loadProjectInTestWindow(testPath);
5459
}, 30000);
@@ -149,5 +154,41 @@ define(function (require, exports, module) {
149154
await closeSession();
150155
});
151156

157+
async function _deleteFile(relativeFileName) {
158+
let deleted = false;
159+
FileSystem.getFileForPath(`${testPath}/${relativeFileName}`).unlink(()=>{
160+
deleted = true;
161+
});
162+
await awaitsFor(function () {
163+
return deleted;
164+
}, "extension interface registration notification");
165+
}
166+
167+
async function createAndVerifyFileContents(fileName, firstLineOfContent) {
168+
await awaitsForDone(CommandManager.execute(Commands.FILE_NEW),
169+
"new file");
170+
await awaits(300);
171+
let fileNameInput = $(".jstree-rename-input");
172+
await _deleteFile(fileName);
173+
fileNameInput.val(fileName);
174+
SpecRunnerUtils.simulateKeyEvent(KeyEvent.DOM_VK_RETURN, "keydown", fileNameInput[0]);
175+
await awaits(100);
176+
expect(EditorManager.getActiveEditor().document.getText().split("\n")[0])
177+
.toBe(firstLineOfContent);
178+
await closeSession();
179+
await _deleteFile(fileName);
180+
}
181+
182+
it("Should creating new html and xhtml file with template contents", async function () {
183+
await createAndVerifyFileContents("test1.html", "<!DOCTYPE html>");
184+
await createAndVerifyFileContents("test1.xhtml",
185+
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtm" +
186+
"l1/DTD/xhtml1-strict.dtd\">");
187+
});
188+
189+
it("Should not put template contents for non html files creation", async function () {
190+
await createAndVerifyFileContents("test1.txt", "");
191+
});
192+
152193
});
153194
});

src/extensions/default/HTMLCodeHints/main.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@ define(function (require, exports, module) {
2929
HTMLUtils = brackets.getModule("language/HTMLUtils"),
3030
PreferencesManager = brackets.getModule("preferences/PreferencesManager"),
3131
Strings = brackets.getModule("strings"),
32+
NewFileContentManager = brackets.getModule("features/NewFileContentManager"),
3233
HTMLTags = require("text!HtmlTags.json"),
33-
HTMLAttributes = require("text!HtmlAttributes.json");
34+
HTMLAttributes = require("text!HtmlAttributes.json"),
35+
HTMLTemplate = require("text!template.html"),
36+
XHTMLTemplate = require("text!template.xhtml");
3437

3538
let tags,
3639
attributes;
@@ -553,16 +556,35 @@ define(function (require, exports, module) {
553556
return false;
554557
};
555558

559+
/**
560+
* @constructor
561+
*/
562+
function NewDocContentProvider() {
563+
this.CONTENT_PROVIDER_NAME = "HTMLCodeHints";
564+
}
565+
566+
NewDocContentProvider.prototype.getContent = function(fileName) {
567+
return new Promise((resolve, reject)=>{
568+
if(fileName.endsWith(".xhtml")){
569+
resolve(XHTMLTemplate);
570+
return;
571+
}
572+
resolve(HTMLTemplate);
573+
});
574+
};
575+
556576
AppInit.appReady(function () {
557577
// Parse JSON files
558578
tags = JSON.parse(HTMLTags);
559579
attributes = JSON.parse(HTMLAttributes);
560580

561581
// Register code hint providers
562-
var tagHints = new TagHints();
563-
var attrHints = new AttrHints();
582+
let tagHints = new TagHints();
583+
let attrHints = new AttrHints();
584+
let newDocContentProvider = new NewDocContentProvider();
564585
CodeHintManager.registerHintProvider(tagHints, ["html"], 0);
565586
CodeHintManager.registerHintProvider(attrHints, ["html"], 0);
587+
NewFileContentManager.registerContentProvider(newDocContentProvider, ["html"], 0);
566588

567589
// For unit testing
568590
exports.tagHintProvider = tagHints;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Title</title>
6+
</head>
7+
<body></body>
8+
</html>

0 commit comments

Comments
 (0)